From d6be71567e7688531361f49d64f5cd85ec18585b Mon Sep 17 00:00:00 2001 From: Marco Date: Sun, 17 May 2026 23:34:51 +0200 Subject: [PATCH 01/83] test: relax min assertion in test-performance-eventloopdelay Signed-off-by: marcopiraccini PR-URL: https://github.com/nodejs/node/pull/63100 Reviewed-By: Paolo Insogna Reviewed-By: Trivikram Kamat --- test/sequential/test-performance-eventloopdelay.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/sequential/test-performance-eventloopdelay.js b/test/sequential/test-performance-eventloopdelay.js index 72e6f7abfef3c2..66493318f5651d 100644 --- a/test/sequential/test-performance-eventloopdelay.js +++ b/test/sequential/test-performance-eventloopdelay.js @@ -71,7 +71,11 @@ const { sleep } = require('internal/util'); // The values are non-deterministic, so we just check that a value is // present, as opposed to a specific value. assert(histogram.count > 0, `Expected samples to be recorded, got count=${histogram.count}`); - assert(histogram.min > 0); + // Min can legitimately be 0: the underlying HDR histogram has a + // lowest discernible value of 1us, so samples whose delta falls in + // the [0, 1us) bucket are reported as 0. A negative value would + // indicate a bug. + assert(histogram.min >= 0); assert(histogram.max > 0); assert(histogram.stddev > 0); assert(histogram.mean > 0); From bc906671a8afce57a41ee981b198ebbc95b25087 Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Sun, 17 May 2026 15:42:17 -0700 Subject: [PATCH 02/83] stream: fix merge handling for object-like sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit merge() treated any final non-iterable object as an options object. That dropped valid from() inputs such as ArrayBuffer, ArrayBufferView, and streamable protocol objects. Fixes: https://github.com/nodejs/node/issues/63355 Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5 PR-URL: https://github.com/nodejs/node/pull/63356 Fixes: https://github.com/nodejs/node/issues/63355 Reviewed-By: James M Snell Reviewed-By: René --- lib/internal/streams/iter/consumers.js | 10 +++++++- .../test-stream-iter-consumers-merge.js | 24 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/internal/streams/iter/consumers.js b/lib/internal/streams/iter/consumers.js index 442fe95b8e1b85..bcfe5d5ab29749 100644 --- a/lib/internal/streams/iter/consumers.js +++ b/lib/internal/streams/iter/consumers.js @@ -8,6 +8,7 @@ // ondrain() - backpressure drain utility const { + ArrayBufferIsView, ArrayBufferPrototypeGetByteLength, ArrayBufferPrototypeSlice, ArrayPrototypeMap, @@ -51,9 +52,12 @@ const { const { drainableProtocol, + toAsyncStreamable, + toStreamable, } = require('internal/streams/iter/types'); const { + isAnyArrayBuffer, isSharedArrayBuffer, } = require('internal/util/types'); @@ -65,8 +69,12 @@ function isMergeOptions(value) { return ( value !== null && typeof value === 'object' && + !ArrayBufferIsView(value) && + typeof value[toStreamable] !== 'function' && + typeof value[toAsyncStreamable] !== 'function' && !isAsyncIterable(value) && - !isSyncIterable(value) + !isSyncIterable(value) && + !isAnyArrayBuffer(value) ); } diff --git a/test/parallel/test-stream-iter-consumers-merge.js b/test/parallel/test-stream-iter-consumers-merge.js index ad047c0ffd7ed4..c5b18be042d874 100644 --- a/test/parallel/test-stream-iter-consumers-merge.js +++ b/test/parallel/test-stream-iter-consumers-merge.js @@ -9,6 +9,8 @@ const { push, merge, text, + toAsyncStreamable, + toStreamable, } = require('stream/iter'); // ============================================================================= @@ -162,6 +164,27 @@ async function testMergeStringSources() { assert.ok(combined.includes('world')); } +// merge() accepts object-like sources that are normalized via from() +async function testMergeObjectLikeSources() { + const arrayBuffer = new TextEncoder().encode('abc').buffer; + const dataView = new DataView(new TextEncoder().encode('def').buffer); + const streamable = { + [toStreamable]() { + return 'ghi'; + }, + }; + const asyncStreamable = { + [toAsyncStreamable]() { + return Promise.resolve('jkl'); + }, + }; + + assert.strictEqual(await text(merge(arrayBuffer)), 'abc'); + assert.strictEqual(await text(merge(dataView)), 'def'); + assert.strictEqual(await text(merge(streamable)), 'ghi'); + assert.strictEqual(await text(merge(asyncStreamable)), 'jkl'); +} + Promise.all([ testMergeTwoSources(), testMergeSingleSource(), @@ -172,4 +195,5 @@ Promise.all([ testMergeConsumerBreak(), testMergeSignalMidIteration(), testMergeStringSources(), + testMergeObjectLikeSources(), ]).then(common.mustCall()); From 1f371fcffbd6424187ee478f20810255c4a9efea Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Sun, 17 May 2026 16:06:55 -0700 Subject: [PATCH 03/83] stream: add sync iterable fast path to pipeTo Avoid normalizing sync iterable sources through from() when pipeTo() has no transforms or signal and the writer can accept sync writes. This keeps writes incremental while preserving async fallback for values that still need it. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5 PR-URL: https://github.com/nodejs/node/pull/63318 Reviewed-By: James M Snell Reviewed-By: Ethan Arrowood --- benchmark/streams/iter-throughput-pipeto.js | 27 +++++++- lib/internal/streams/iter/pull.js | 58 ++++++++++++++-- test/parallel/test-stream-iter-pipeto.js | 76 +++++++++++++++++++++ 3 files changed, 155 insertions(+), 6 deletions(-) diff --git a/benchmark/streams/iter-throughput-pipeto.js b/benchmark/streams/iter-throughput-pipeto.js index 117a78aead1088..819d5e22a8a272 100644 --- a/benchmark/streams/iter-throughput-pipeto.js +++ b/benchmark/streams/iter-throughput-pipeto.js @@ -6,7 +6,7 @@ const common = require('../common.js'); const { Readable, Writable, pipeline } = require('stream'); const bench = common.createBenchmark(main, { - api: ['classic', 'webstream', 'iter', 'iter-sync'], + api: ['classic', 'webstream', 'iter', 'iter-sync-source', 'iter-sync'], datasize: [1024 * 1024, 16 * 1024 * 1024, 64 * 1024 * 1024], n: [5], }, { @@ -26,6 +26,8 @@ function main({ api, datasize, n }) { return benchWebStream(chunk, datasize, n, totalOps); case 'iter': return benchIter(chunk, datasize, n, totalOps); + case 'iter-sync-source': + return benchIterSyncSource(chunk, datasize, n, totalOps); case 'iter-sync': return benchIterSync(chunk, datasize, n, totalOps); } @@ -101,6 +103,29 @@ function benchIter(chunk, datasize, n, totalOps) { })(); } +function benchIterSyncSource(chunk, datasize, n, totalOps) { + const { pipeTo } = require('stream/iter'); + + async function run() { + let remaining = datasize; + function* source() { + while (remaining > 0) { + const size = Math.min(remaining, chunk.length); + remaining -= size; + yield size === chunk.length ? chunk : chunk.subarray(0, size); + } + } + const writer = { write() {}, writeSync() { return true; } }; + await pipeTo(source(), writer); + } + + (async () => { + bench.start(); + for (let i = 0; i < n; i++) await run(); + bench.end(totalOps); + })(); +} + function benchIterSync(chunk, datasize, n, totalOps) { const { pipeToSync } = require('stream/iter'); diff --git a/lib/internal/streams/iter/pull.js b/lib/internal/streams/iter/pull.js index 5b004c58a5e995..3ff88b251d182a 100644 --- a/lib/internal/streams/iter/pull.js +++ b/lib/internal/streams/iter/pull.js @@ -8,6 +8,8 @@ const { ArrayBufferIsView, + ArrayFromAsync, + ArrayIsArray, ArrayPrototypePush, ArrayPrototypeSlice, PromisePrototypeThen, @@ -38,7 +40,9 @@ const { fromSync, isSyncIterable, isAsyncIterable, + isPrimitiveChunk, isUint8ArrayBatch, + normalizeAsyncValue, } = require('internal/streams/iter/from'); const { @@ -53,7 +57,10 @@ const { const { drainableProtocol, kSyncWriteAcceptedOnFalse, + kValidatedSource, kValidatedTransform, + toAsyncStreamable, + toStreamable, } = require('internal/streams/iter/types'); // ============================================================================= @@ -116,6 +123,22 @@ function parsePipeToArgs(args, requiredMethod) { }; } +function canUseSyncIterablePipeToFastPath(source, transforms, signal) { + if (signal !== undefined || + transforms.length !== 0 || + isPrimitiveChunk(source) || + ArrayIsArray(source) || + source?.[kValidatedSource] || + !isSyncIterable(source) || + isAsyncIterable(source)) { + return false; + } + + // Preserve from()'s top-level protocol precedence for custom iterables. + return typeof source[toAsyncStreamable] !== 'function' && + typeof source[toStreamable] !== 'function'; +} + // ============================================================================= // Transform Output Flattening // ============================================================================= @@ -822,12 +845,13 @@ async function pipeTo(source, ...args) { // Check for abort signal?.throwIfAborted(); - // Normalize source via from() - const normalized = from(source); + const hasWriteSync = typeof writer.writeSync === 'function'; + const useSyncIterableFastPath = + hasWriteSync && canUseSyncIterablePipeToFastPath(source, transforms, signal); + const normalized = useSyncIterableFastPath ? undefined : from(source); let totalBytes = 0; const hasWritev = typeof writer.writev === 'function'; - const hasWriteSync = typeof writer.writeSync === 'function'; const hasWritevSync = typeof writer.writevSync === 'function'; const hasEndSync = typeof writer.endSync === 'function'; const syncFalseCanBeAccepted = writer[kSyncWriteAcceptedOnFalse] === true; @@ -908,8 +932,32 @@ async function pipeTo(source, ...args) { } try { - // Fast path: no transforms - iterate normalized source directly - if (transforms.length === 0) { + if (useSyncIterableFastPath) { + // Avoid from()'s async sync-iterable batching path. This keeps writes + // incremental for synchronous sources while preserving async + // normalization for non-primitive yielded values. + for (const value of source) { + if (isUint8ArrayBatch(value)) { + if (value.length > 0) { + const p = writeBatch(value); + if (p) await p; + } + continue; + } + if (isUint8Array(value)) { + const p = writeBatch([value]); + if (p) await p; + continue; + } + + const batch = await ArrayFromAsync(normalizeAsyncValue(value)); + if (batch.length > 0) { + const p = writeBatch(batch); + if (p) await p; + } + } + } else if (transforms.length === 0) { + // Fast path: no transforms - iterate normalized source directly if (signal) { for await (const batch of normalized) { signal.throwIfAborted(); diff --git a/test/parallel/test-stream-iter-pipeto.js b/test/parallel/test-stream-iter-pipeto.js index 9845a5ba254efb..bc6fa9d4984233 100644 --- a/test/parallel/test-stream-iter-pipeto.js +++ b/test/parallel/test-stream-iter-pipeto.js @@ -219,6 +219,79 @@ async function testPipeToSyncMinimalWriter() { assert.strictEqual(chunks.length > 0, true); } +async function testPipeToSyncIterableFastPathWritesIncrementally() { + let pulled = 0; + let firstWritePulled = 0; + const chunks = []; + function* source() { + for (let i = 0; i < 3; i++) { + pulled++; + yield new Uint8Array([0x61 + i]); + } + } + const writer = { + write: common.mustNotCall(), + writeSync(chunk) { + if (firstWritePulled === 0) { + firstWritePulled = pulled; + } + chunks.push(chunk); + return true; + }, + }; + + const totalBytes = await pipeTo(source(), writer); + assert.strictEqual(totalBytes, 3); + assert.strictEqual(firstWritePulled, 1); + assert.deepStrictEqual(chunks, [ + new Uint8Array([0x61]), + new Uint8Array([0x62]), + new Uint8Array([0x63]), + ]); +} + +async function testPipeToSyncIterableFastPathWriteFallback() { + const asyncWrites = []; + const writer = { + writeSync(chunk) { + return chunk[0] !== 0x62; + }, + async write(chunk) { + asyncWrites.push(chunk); + }, + }; + function* source() { + yield new Uint8Array([0x61]); + yield new Uint8Array([0x62]); + yield new Uint8Array([0x63]); + } + + const totalBytes = await pipeTo(source(), writer); + assert.strictEqual(totalBytes, 3); + assert.deepStrictEqual(asyncWrites, [new Uint8Array([0x62])]); +} + +async function testPipeToSyncIterableFastPathAsyncValue() { + const chunks = []; + const writer = { + write: common.mustNotCall(), + writeSync(chunk) { + chunks.push(chunk); + return true; + }, + }; + function* source() { + yield Promise.resolve('a'); + yield new Uint8Array([0x62]); + } + + const totalBytes = await pipeTo(source(), writer); + assert.strictEqual(totalBytes, 2); + const result = new TextDecoder().decode( + new Uint8Array(chunks.reduce((acc, c) => [...acc, ...c], []))); + assert.strictEqual(result, 'ab'); +} + Promise.all([ testPipeToSync(), testPipeTo(), @@ -234,4 +307,7 @@ Promise.all([ testPipeToSyncPreventClose(), testPipeToMinimalWriter(), testPipeToSyncMinimalWriter(), + testPipeToSyncIterableFastPathWritesIncrementally(), + testPipeToSyncIterableFastPathWriteFallback(), + testPipeToSyncIterableFastPathAsyncValue(), ]).then(common.mustCall()); From debe2ed2efd377d301282e4c64489ca2a9d7b028 Mon Sep 17 00:00:00 2001 From: Ali Hassan <24819103+thisalihassan@users.noreply.github.com> Date: Mon, 18 May 2026 12:54:35 +0500 Subject: [PATCH 04/83] test_runner: avoid hanging on incomplete v8 frames Signed-off-by: Ali Hassan PR-URL: https://github.com/nodejs/node/pull/62704 Reviewed-By: Moshe Atlow Reviewed-By: Chemi Atlow --- lib/internal/test_runner/runner.js | 54 ++++++++++-- test/parallel/test-runner-v8-deserializer.mjs | 88 ++++++++++++++++--- 2 files changed, 124 insertions(+), 18 deletions(-) diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js index 1b0dfb51b21fbe..d6cb6438d2b52a 100644 --- a/lib/internal/test_runner/runner.js +++ b/lib/internal/test_runner/runner.js @@ -25,6 +25,7 @@ const { SafePromiseAllSettledReturnVoid, SafeSet, String, + StringFromCharCode, StringPrototypeIndexOf, StringPrototypeSlice, StringPrototypeStartsWith, @@ -261,6 +262,7 @@ class FileTest extends Test { #rawBuffer = []; // Raw data waiting to be parsed #rawBufferSize = 0; #reportedChildren = 0; + #pendingPartialV8Header = false; failedSubtests = false; constructor(options) { @@ -352,6 +354,12 @@ class FileTest extends Test { } parseMessage(readData) { let dataLength = TypedArrayPrototypeGetLength(readData); + if (this.#pendingPartialV8Header) { + readData = Buffer.concat([TypedArrayPrototypeSubarray(v8Header, 0, 1), readData]); + dataLength = TypedArrayPrototypeGetLength(readData); + this.#pendingPartialV8Header = false; + } + if (dataLength === 0) return; const partialV8Header = readData[dataLength - 1] === v8Header[0]; @@ -362,22 +370,52 @@ class FileTest extends Test { dataLength--; } - if (this.#rawBuffer[0] && TypedArrayPrototypeGetLength(this.#rawBuffer[0]) < kSerializedSizeHeader) { - this.#rawBuffer[0] = Buffer.concat([this.#rawBuffer[0], readData]); - } else { - ArrayPrototypePush(this.#rawBuffer, readData); + if (dataLength > 0) { + if (this.#rawBuffer[0] && TypedArrayPrototypeGetLength(this.#rawBuffer[0]) < kSerializedSizeHeader) { + this.#rawBuffer[0] = Buffer.concat([this.#rawBuffer[0], readData]); + } else { + ArrayPrototypePush(this.#rawBuffer, readData); + } + this.#rawBufferSize += dataLength; + this.#processRawBuffer(); } - this.#rawBufferSize += dataLength; - this.#processRawBuffer(); if (partialV8Header) { - ArrayPrototypePush(this.#rawBuffer, TypedArrayPrototypeSubarray(v8Header, 0, 1)); - this.#rawBufferSize++; + this.#pendingPartialV8Header = true; } } #drainRawBuffer() { + if (this.#pendingPartialV8Header) { + ArrayPrototypePush(this.#rawBuffer, TypedArrayPrototypeSubarray(v8Header, 0, 1)); + this.#rawBufferSize++; + this.#pendingPartialV8Header = false; + } + while (this.#rawBuffer.length > 0) { + const prevBufferLength = this.#rawBuffer.length; + const prevBufferSize = this.#rawBufferSize; this.#processRawBuffer(); + + if (this.#rawBuffer.length === prevBufferLength && + this.#rawBufferSize === prevBufferSize) { + const bufferHead = this.#rawBuffer[0]; + this.addToReport({ + __proto__: null, + type: 'test:stdout', + data: { + __proto__: null, + file: this.name, + message: StringFromCharCode(bufferHead[0]), + }, + }); + + if (TypedArrayPrototypeGetLength(bufferHead) === 1) { + ArrayPrototypeShift(this.#rawBuffer); + } else { + this.#rawBuffer[0] = TypedArrayPrototypeSubarray(bufferHead, 1); + } + this.#rawBufferSize--; + } } } #processRawBuffer() { diff --git a/test/parallel/test-runner-v8-deserializer.mjs b/test/parallel/test-runner-v8-deserializer.mjs index 0f6fea1e64b58d..5e50df441da59e 100644 --- a/test/parallel/test-runner-v8-deserializer.mjs +++ b/test/parallel/test-runner-v8-deserializer.mjs @@ -14,12 +14,29 @@ async function toArray(chunks) { return arr; } -const chunks = await toArray(serializer([ - { type: 'test:diagnostic', data: { nesting: 0, details: {}, message: 'diagnostic' } }, -])); +const diagnosticEvent = { + type: 'test:diagnostic', + data: { nesting: 0, details: {}, message: 'diagnostic' }, +}; +const chunks = await toArray(serializer([diagnosticEvent])); const defaultSerializer = new DefaultSerializer(); defaultSerializer.writeHeader(); const headerLength = defaultSerializer.releaseBuffer().length; +const headerOnly = Buffer.from([0xff, 0x0f]); +const oversizedLengthHeader = Buffer.from([0xff, 0x0f, 0x7f, 0xff, 0xff, 0xff]); +const truncatedLengthHeader = Buffer.from([0xff, 0x0f, 0x00, 0x01, 0x00, 0x00]); +// Expected stdout for oversizedLengthHeader: first byte is emitted via +// String.fromCharCode (byte-by-byte fallback in #drainRawBuffer), remaining +// bytes go through the nonSerialized UTF-8 decode path in #processRawBuffer. +const oversizedLengthStdout = String.fromCharCode(oversizedLengthHeader[0]) + + Buffer.from(oversizedLengthHeader.subarray(1)).toString('utf-8'); + +function collectStdout(reported) { + return reported + .filter((event) => event.type === 'test:stdout') + .map((event) => event.data.message) + .join(''); +} describe('v8 deserializer', common.mustCall(() => { let fileTest; @@ -56,27 +73,78 @@ describe('v8 deserializer', common.mustCall(() => { it('should deserialize a serialized chunk', async () => { const reported = await collectReported(chunks); - assert.deepStrictEqual(reported, [ - { data: { nesting: 0, details: {}, message: 'diagnostic' }, type: 'test:diagnostic' }, - ]); + assert.deepStrictEqual(reported, [diagnosticEvent]); }); it('should deserialize a serialized chunk after non-serialized chunk', async () => { const reported = await collectReported([Buffer.concat([Buffer.from('unknown'), ...chunks])]); assert.deepStrictEqual(reported, [ { data: { __proto__: null, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, - { data: { nesting: 0, details: {}, message: 'diagnostic' }, type: 'test:diagnostic' }, + diagnosticEvent, ]); }); it('should deserialize a serialized chunk before non-serialized output', async () => { const reported = await collectReported([Buffer.concat([ ...chunks, Buffer.from('unknown')])]); assert.deepStrictEqual(reported, [ - { data: { nesting: 0, details: {}, message: 'diagnostic' }, type: 'test:diagnostic' }, + diagnosticEvent, { data: { __proto__: null, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, ]); }); + it('should not hang when buffer starts with v8Header followed by oversized length', async () => { + // Regression test for https://github.com/nodejs/node/issues/62693 + // FF 0F is the v8 serializer header; the next 4 bytes are read as a + // big-endian message size. 0x7FFFFFFF far exceeds any actual buffer + // size, causing #processRawBuffer to make no progress and + // #drainRawBuffer to loop forever without the no-progress guard. + const reported = await collectReported([oversizedLengthHeader]); + assert.partialDeepStrictEqual( + reported, + Array.from({ length: reported.length }, () => ({ type: 'test:stdout' })), + ); + assert.strictEqual(collectStdout(reported), oversizedLengthStdout); + }); + + it('should flush incomplete v8 frame as stdout and keep prior valid data', async () => { + // A valid non-serialized message followed by bytes that look like + // a v8 header with a truncated/oversized length. + const reported = await collectReported([ + Buffer.from('hello'), + truncatedLengthHeader, + ]); + assert.strictEqual(collectStdout(reported), `hello${truncatedLengthHeader.toString('latin1')}`); + }); + + it('should flush v8Header-only bytes as stdout when stream ends', async () => { + // Just the two-byte v8 header with no size field at all. + const reported = await collectReported([headerOnly]); + assert(reported.every((event) => event.type === 'test:stdout')); + assert.strictEqual(collectStdout(reported), headerOnly.toString('latin1')); + }); + + it('should resync and parse valid messages after false v8 header', async () => { + // A false v8 header (FF 0F + oversized length) followed by a + // legitimate serialized message. The parser must skip the corrupt + // bytes and still deserialize the real message. + const reported = await collectReported([ + oversizedLengthHeader, + ...chunks, + ]); + assert.deepStrictEqual(reported.at(-1), diagnosticEvent); + assert.strictEqual(reported.filter((event) => event.type === 'test:diagnostic').length, 1); + assert.strictEqual(collectStdout(reported), oversizedLengthStdout); + }); + + it('should preserve a false v8 header split across chunks', async () => { + const reported = await collectReported([ + oversizedLengthHeader.subarray(0, 1), + oversizedLengthHeader.subarray(1), + ]); + assert(reported.every((event) => event.type === 'test:stdout')); + assert.strictEqual(collectStdout(reported), oversizedLengthStdout); + }); + const headerPosition = headerLength * 2 + 4; for (let i = 0; i < headerPosition + 5; i++) { const message = `should deserialize a serialized message split into two chunks {...${i},${i + 1}...}`; @@ -84,7 +152,7 @@ describe('v8 deserializer', common.mustCall(() => { const data = chunks[0]; const reported = await collectReported([data.subarray(0, i), data.subarray(i)]); assert.deepStrictEqual(reported, [ - { data: { nesting: 0, details: {}, message: 'diagnostic' }, type: 'test:diagnostic' }, + diagnosticEvent, ]); }); @@ -96,7 +164,7 @@ describe('v8 deserializer', common.mustCall(() => { ]); assert.deepStrictEqual(reported, [ { data: { __proto__: null, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, - { data: { nesting: 0, details: {}, message: 'diagnostic' }, type: 'test:diagnostic' }, + diagnosticEvent, { data: { __proto__: null, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, ]); } From 3b19867caaef6b85c65e44dc60274dce2b240d22 Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Mon, 18 May 2026 03:42:45 -0700 Subject: [PATCH 05/83] benchmark: respect stream/iter broadcast backpressure Only decrement the remaining byte count after a stream/iter broadcast write is accepted. If writeSync() is blocked by strict backpressure, fall back to the async write() path for the same chunk. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5 PR-URL: https://github.com/nodejs/node/pull/63314 Reviewed-By: James M Snell Reviewed-By: Antoine du Hamel --- benchmark/streams/iter-throughput-broadcast.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/benchmark/streams/iter-throughput-broadcast.js b/benchmark/streams/iter-throughput-broadcast.js index 459d78e7c75f25..c5bbac9306777e 100644 --- a/benchmark/streams/iter-throughput-broadcast.js +++ b/benchmark/streams/iter-throughput-broadcast.js @@ -128,9 +128,11 @@ function benchIter(chunk, numConsumers, datasize, n, totalOps) { let remaining = datasize; while (remaining > 0) { const size = Math.min(remaining, chunk.length); - remaining -= size; const buf = size === chunk.length ? chunk : chunk.subarray(0, size); - writer.writeSync(buf); + if (!writer.writeSync(buf)) { + await writer.write(buf); + } + remaining -= size; } writer.endSync(); From f2aaf638465db9a545f33a6bfb416ffd952ffba3 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Mon, 18 May 2026 19:45:55 +0200 Subject: [PATCH 06/83] test: fix flaky test-watch-mode-inspect timeout This test randomly times out (~120s) on CI due to a race condition between child-process restart (triggered by touching the watched file) and the second inspector-session connection. The old code used an interval-based restart (write every 500ms) and a 'gettingDebuggedPid' flag to pause writes during a session. This still left a race window where getDebuggedPid() would attempt to connect the inspector via HTTP GET /json/list + WebSocket upgrade either before the new child was ready (empty target list) or after the old session was being destroyed, causing the promise to hang. Fix: Replace the interval with a single write that triggers exactly one restart, then wait for the restarted child's 'safe to debug now' stdout line before connecting the second inspector session. This eliminates the race by ensuring the new child process and its inspector session are fully ready before any connection attempt. Removes the now-unused gettingDebuggedPid flag and the pending setTimeout delay that was needed as a backstop for the interval. Fixes: https://github.com/nodejs/node/issues/44898 Signed-off-by: Matteo Collina PR-URL: https://github.com/nodejs/node/pull/63361 Reviewed-By: Moshe Atlow Reviewed-By: Paolo Insogna --- test/sequential/test-watch-mode-inspect.mjs | 27 +++++++++------------ 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/test/sequential/test-watch-mode-inspect.mjs b/test/sequential/test-watch-mode-inspect.mjs index f2886f11b56da4..d00036d3b859da 100644 --- a/test/sequential/test-watch-mode-inspect.mjs +++ b/test/sequential/test-watch-mode-inspect.mjs @@ -3,7 +3,6 @@ import * as fixtures from '../common/fixtures.mjs'; import assert from 'node:assert'; import { describe, it } from 'node:test'; import { writeFileSync, readFileSync } from 'node:fs'; -import { setTimeout } from 'node:timers/promises'; import { NodeInstance } from '../common/inspector-helper.js'; @@ -12,10 +11,7 @@ if (common.isIBMi) common.skipIfInspectorDisabled(); -let gettingDebuggedPid = false; - async function getDebuggedPid(instance, waitForLog = true) { - gettingDebuggedPid = true; const session = await instance.connectInspectorSession(); await session.send({ method: 'Runtime.enable' }); if (waitForLog) { @@ -25,20 +21,23 @@ async function getDebuggedPid(instance, waitForLog = true) { 'method': 'Runtime.evaluate', 'params': { 'expression': 'process.pid' }, })).result; session.disconnect(); - gettingDebuggedPid = false; return innerPid; } -function restart(file) { +// Triggers a single restart and resolves when the restarted child prints "safe to debug now". +function restartAndWaitForReady(file, instance) { + const ready = new Promise((resolve) => { + instance.on('stdout', (data) => { + if (data?.includes('safe to debug now')) { + resolve(); + } + }); + }); writeFileSync(file, readFileSync(file)); - const interval = setInterval(() => { - if (!gettingDebuggedPid) { - writeFileSync(file, readFileSync(file)); - } - }, common.platformTimeout(500)); - return () => clearInterval(interval); + return ready; } + describe('watch mode - inspect', () => { it('should start debugger on inner process', async () => { const file = fixtures.path('watch-mode/inspect.js'); @@ -51,11 +50,9 @@ describe('watch mode - inspect', () => { const pids = [instance.pid]; pids.push(await getDebuggedPid(instance)); instance.resetPort(); - const stopRestarting = restart(file); + await restartAndWaitForReady(file, instance); pids.push(await getDebuggedPid(instance)); - stopRestarting(); - await setTimeout(common.platformTimeout(500)); await instance.kill(); // There should be a process per restart and one per parent process. From 155268f786e58164bff31797b6442e8f50d3c269 Mon Sep 17 00:00:00 2001 From: Mike McCready <66998419+MikeMcC399@users.noreply.github.com> Date: Mon, 18 May 2026 19:46:09 +0200 Subject: [PATCH 07/83] doc: add Rust toolchain manual installation instructions Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mike McCready <66998419+MikeMcC399@users.noreply.github.com> PR-URL: https://github.com/nodejs/node/pull/63367 Refs: https://github.com/nodejs/node/issues/63225 Reviewed-By: Chengzhong Wu Reviewed-By: Matteo Collina Reviewed-By: Luigi Pinca Reviewed-By: Ulises Gascón Reviewed-By: Stefan Stojanovic --- BUILDING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/BUILDING.md b/BUILDING.md index 7597f0114e7f76..5cf5e9f57d6753 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -755,6 +755,10 @@ Refs: * As an alternative to Visual Studio 2026, download Visual Studio 2022 Current channel Version 17.14 from the [Evergreen bootstrappers](https://learn.microsoft.com/en-us/visualstudio/releases/2022/release-history#evergreen-bootstrappers) table and install using the same workload and optional component selection as described above. +* To install the Rust toolchain, required for Temporal support introduced in Node.js 26, + ensure Visual Studio is already installed, then run `rustup-init.exe` downloaded from + [Install Rust](https://rust-lang.org/tools/install/), + choosing the default: "Proceed with standard installation". * Basic Unix tools required for some tests, [Git for Windows](https://git-scm.com/download/win) includes Git Bash and tools which can be included in the global `PATH`. From 4ee756741b41592ad80bfb7d95d0011d756ed744 Mon Sep 17 00:00:00 2001 From: Livia Medeiros Date: Tue, 19 May 2026 06:18:00 +0800 Subject: [PATCH 08/83] fs: add `Temporal.Instant` support to `Stats` and `BigIntStats` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: LiviaMedeiros PR-URL: https://github.com/nodejs/node/pull/60789 Refs: https://github.com/nodejs/node/issues/57891 Reviewed-By: Antoine du Hamel Reviewed-By: James M Snell Reviewed-By: René --- doc/api/errors.md | 13 ++ doc/api/fs.md | 37 +++++- lib/internal/errors.js | 2 + lib/internal/fs/utils.js | 154 ++++++++++++++++++++++-- test/parallel/test-fs-stat-temporal.mjs | 105 ++++++++++++++++ test/parallel/test-fs-watchfile.js | 12 +- 6 files changed, 304 insertions(+), 19 deletions(-) create mode 100644 test/parallel/test-fs-stat-temporal.mjs diff --git a/doc/api/errors.md b/doc/api/errors.md index f2aafb1b165ca7..8e0956c29f3843 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -2465,6 +2465,18 @@ OpenSSL crypto support. An attempt was made to use features that require [ICU][], but Node.js was not compiled with ICU support. + + +### `ERR_NO_TEMPORAL` + + + +An attempt was made to use features that require [`Temporal`][], but Node.js was not +compiled with `Temporal` support or it has been disabled in the current environment +(for example, when running with `--no-harmony-temporal`). + ### `ERR_NO_TYPESCRIPT` @@ -4472,6 +4484,7 @@ An error occurred trying to allocate memory. This should never happen. [`QuicError`]: quic.md#class-quicerror [`REPL`]: repl.md [`ServerResponse`]: http.md#class-httpserverresponse +[`Temporal`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal [`Writable`]: stream.md#class-streamwritable [`child_process`]: child_process.md [`cipher.getAuthTag()`]: crypto.md#ciphergetauthtag diff --git a/doc/api/fs.md b/doc/api/fs.md index c5e908aaa39f6c..884e5935219b67 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4799,7 +4799,11 @@ Stats { atime: 2019-06-22T03:37:33.072Z, mtime: 2019-06-22T03:36:54.583Z, ctime: 2019-06-22T03:37:06.624Z, - birthtime: 2019-06-22T03:28:46.937Z + birthtime: 2019-06-22T03:28:46.937Z, + atimeInstant: 2019-06-22T03:37:33.071963Z, + mtimeInstant: 2019-06-22T03:36:54.5833518Z, + ctimeInstant: 2019-06-22T03:37:06.6235366Z, + birthtimeInstant: 2019-06-22T03:28:46.9372893Z } false Stats { @@ -4820,7 +4824,11 @@ Stats { atime: 2019-06-22T03:36:56.619Z, mtime: 2019-06-22T03:36:54.584Z, ctime: 2019-06-22T03:36:54.584Z, - birthtime: 2019-06-22T03:26:47.711Z + birthtime: 2019-06-22T03:26:47.711Z, + atimeInstant: 2019-06-22T03:36:56.6188555Z, + mtimeInstant: 2019-06-22T03:36:54.584Z, + ctimeInstant: 2019-06-22T03:36:54.5838145Z, + birthtimeInstant: 2019-06-22T03:26:47.7107478Z } ``` @@ -7525,6 +7533,9 @@ i.e. before the `'ready'` event is emitted. * `algorithm` {string | null | undefined} -* `data` {ArrayBuffer|Buffer|TypedArray|DataView} +* `data` {ArrayBuffer|Buffer|SharedArrayBuffer|TypedArray|DataView|string} * `key` {Object|string|ArrayBuffer|Buffer|TypedArray|DataView|KeyObject|CryptoKey} * `callback` {Function} * `err` {Error} @@ -6264,9 +6264,9 @@ changes: * `algorithm` {string|null|undefined} -* `data` {ArrayBuffer| Buffer|TypedArray|DataView} +* `data` {ArrayBuffer|Buffer|SharedArrayBuffer|TypedArray|DataView|string} * `key` {Object|string|ArrayBuffer|Buffer|TypedArray|DataView|KeyObject|CryptoKey} -* `signature` {ArrayBuffer|Buffer|TypedArray|DataView} +* `signature` {ArrayBuffer|Buffer|SharedArrayBuffer|TypedArray|DataView} * `callback` {Function} * `err` {Error} * `result` {boolean} diff --git a/lib/internal/crypto/sig.js b/lib/internal/crypto/sig.js index a27ce4b190e111..3830ecc0b128d2 100644 --- a/lib/internal/crypto/sig.js +++ b/lib/internal/crypto/sig.js @@ -265,14 +265,6 @@ function verifyOneShot(algorithm, data, key, signature, callback) { data = getArrayBufferOrView(data, 'data'); - if (!isArrayBufferView(data)) { - throw new ERR_INVALID_ARG_TYPE( - 'data', - ['Buffer', 'TypedArray', 'DataView'], - data, - ); - } - // Options specific to RSA const rsaPadding = getPadding(key); const pssSaltLength = getSaltLength(key); @@ -283,13 +275,7 @@ function verifyOneShot(algorithm, data, key, signature, callback) { // Options specific to Ed448 and ML-DSA const context = getContext(key); - if (!isArrayBufferView(signature)) { - throw new ERR_INVALID_ARG_TYPE( - 'signature', - ['Buffer', 'TypedArray', 'DataView'], - signature, - ); - } + signature = getArrayBufferOrView(signature, 'signature'); const { data: keyData, diff --git a/test/parallel/test-crypto-sign-verify.js b/test/parallel/test-crypto-sign-verify.js index a33eeca328ce8d..a6a0d339d2432d 100644 --- a/test/parallel/test-crypto-sign-verify.js +++ b/test/parallel/test-crypto-sign-verify.js @@ -619,8 +619,8 @@ if (hasOpenSSL(3, 2)) { assert.throws(() => crypto.sign(null, data, input), errObj); assert.throws(() => crypto.verify(null, data, input, sig), errObj); - errObj.message = 'The "signature" argument must be an instance of ' + - 'Buffer, TypedArray, or DataView.' + + errObj.message = 'The "signature" argument must be of type string or an instance of ' + + 'ArrayBuffer, Buffer, TypedArray, or DataView.' + common.invalidArgTypeHelper(input); assert.throws(() => crypto.verify(null, data, 'test', input), errObj); }); @@ -1019,3 +1019,39 @@ if (!process.features.openssl_is_boringssl) { message: /key\.format/, }); } + +// crypto.verify accepts ArrayBuffer and SharedArrayBuffer for data and signature +{ + const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', { modulusLength: 2048 }); + const dataBuffer = Buffer.from('Hello world'); + + // Data as ArrayBuffer + { + const ab = dataBuffer.buffer.slice(dataBuffer.byteOffset, dataBuffer.byteOffset + dataBuffer.byteLength); + const sig = crypto.sign('SHA256', dataBuffer, privateKey); + assert.strictEqual(crypto.verify('SHA256', ab, publicKey, sig), true); + } + + // Data as SharedArrayBuffer + { + const sab = new SharedArrayBuffer(dataBuffer.length); + new Uint8Array(sab).set(dataBuffer); + const sig = crypto.sign('SHA256', dataBuffer, privateKey); + assert.strictEqual(crypto.verify('SHA256', sab, publicKey, sig), true); + } + + // Signature as ArrayBuffer + { + const sig = crypto.sign('SHA256', dataBuffer, privateKey); + const sigAB = sig.buffer.slice(sig.byteOffset, sig.byteOffset + sig.byteLength); + assert.strictEqual(crypto.verify('SHA256', dataBuffer, publicKey, sigAB), true); + } + + // Signature as SharedArrayBuffer + { + const sig = crypto.sign('SHA256', dataBuffer, privateKey); + const sigSAB = new SharedArrayBuffer(sig.length); + new Uint8Array(sigSAB).set(sig); + assert.strictEqual(crypto.verify('SHA256', dataBuffer, publicKey, sigSAB), true); + } +} From 57ee68239c501e3bc01fa3ba30e9e83178ab8074 Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Tue, 19 May 2026 10:49:31 -0700 Subject: [PATCH 17/83] test: deflake watch mode worker test Trigger watch restarts by appending whitespace instead of rewriting watched modules. This avoids transient empty or partial ESM dependency contents while the restarted worker is loading. Use a separate temporary directory for each subtest so concurrent subtests do not share worker and dependency file names. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5 PR-URL: https://github.com/nodejs/node/pull/63384 Refs: https://github.com/nodejs/reliability/blob/main/reports/2026-05-17.md#jstest-failure Reviewed-By: Luigi Pinca Reviewed-By: Antoine du Hamel --- test/sequential/test-watch-mode-worker.mjs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/test/sequential/test-watch-mode-worker.mjs b/test/sequential/test-watch-mode-worker.mjs index b7bc1a94a87ba4..41cdf05782cd38 100644 --- a/test/sequential/test-watch-mode-worker.mjs +++ b/test/sequential/test-watch-mode-worker.mjs @@ -5,7 +5,7 @@ import path from 'node:path'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; import { spawn } from 'node:child_process'; -import { writeFileSync, readFileSync } from 'node:fs'; +import { appendFileSync, mkdirSync, writeFileSync } from 'node:fs'; import { inspect } from 'node:util'; import { pathToFileURL } from 'node:url'; import { createInterface } from 'node:readline'; @@ -13,9 +13,9 @@ import { createInterface } from 'node:readline'; if (common.isIBMi) common.skip('IBMi does not support `fs.watch()`'); -function restart(file, content = readFileSync(file)) { - writeFileSync(file, content); - const timer = setInterval(() => writeFileSync(file, content), common.platformTimeout(250)); +function restart(file) { + appendFileSync(file, '\n'); + const timer = setInterval(() => appendFileSync(file, '\n'), common.platformTimeout(250)); return () => clearInterval(timer); } @@ -26,6 +26,12 @@ function createTmpFile(content = 'console.log(\'running\');', ext = '.js', basen return file; } +function createTmpDir() { + const dir = path.join(tmpdir.path, `${tmpFiles++}`); + mkdirSync(dir); + return dir; +} + async function runWriteSucceed({ file, watchedFile, @@ -78,10 +84,10 @@ async function runWriteSucceed({ } tmpdir.refresh(); -const dir = tmpdir.path; describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_000 }, () => { it('should watch changes to worker - cjs', async () => { + const dir = createTmpDir(); const worker = path.join(dir, 'worker.js'); writeFileSync(worker, ` @@ -109,6 +115,7 @@ const w = new Worker(${JSON.stringify(worker)}); }); it('should watch changes to worker dependencies - cjs', async () => { + const dir = createTmpDir(); const dep = path.join(dir, 'dep.js'); const worker = path.join(dir, 'worker.js'); @@ -142,6 +149,7 @@ const w = new Worker(${JSON.stringify(worker)}); }); it('should watch changes to nested worker dependencies - cjs', async () => { + const dir = createTmpDir(); const subDep = path.join(dir, 'sub-dep.js'); const dep = path.join(dir, 'dep.js'); const worker = path.join(dir, 'worker.js'); @@ -181,6 +189,7 @@ const w = new Worker(${JSON.stringify(worker)}); }); it('should watch changes to worker - esm', async () => { + const dir = createTmpDir(); const worker = path.join(dir, 'worker.mjs'); writeFileSync(worker, ` @@ -208,6 +217,7 @@ new Worker(new URL(${JSON.stringify(pathToFileURL(worker))})); }); it('should watch changes to worker dependencies - esm', async () => { + const dir = createTmpDir(); const dep = path.join(dir, 'dep.mjs'); const worker = path.join(dir, 'worker.mjs'); @@ -241,6 +251,7 @@ new Worker(new URL(${JSON.stringify(pathToFileURL(worker))})); }); it('should watch changes to nested worker dependencies - esm', async () => { + const dir = createTmpDir(); const subDep = path.join(dir, 'sub-dep.mjs'); const dep = path.join(dir, 'dep.mjs'); const worker = path.join(dir, 'worker.mjs'); From b1387e6aedc5e05d11939efd3bb5b8c3caf5fc22 Mon Sep 17 00:00:00 2001 From: Daijiro Wachi Date: Wed, 20 May 2026 03:30:44 +0900 Subject: [PATCH 18/83] lib: use `Object.freeze` to avoid defensive cloning in `SourceMap` PR-URL: https://github.com/nodejs/node/pull/62830 Reviewed-By: Chengzhong Wu Reviewed-By: Yagiz Nizipli --- doc/api/module.md | 11 +++++++++++ lib/internal/source_map/source_map.js | 14 ++++++-------- test/parallel/test-source-map-api.js | 13 +++++++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/doc/api/module.md b/doc/api/module.md index 5ab07802e0588f..451c8b3348a47a 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -1962,10 +1962,20 @@ generated code. #### `sourceMap.payload` + + * Returns: {Object} Getter for the payload used to construct the [`SourceMap`][] instance. +The returned object is frozen with [`Object.freeze()`][], and the same +reference is returned on every access. Do not mutate the returned object. + #### `sourceMap.findEntry(lineOffset, columnOffset)` * `lineOffset` {number} The zero-indexed line number offset in @@ -2050,6 +2060,7 @@ returned object contains the following keys: [`NODE_COMPILE_CACHE_PORTABLE=1`]: cli.md#node_compile_cache_portable1 [`NODE_DISABLE_COMPILE_CACHE=1`]: cli.md#node_disable_compile_cache1 [`NODE_V8_COVERAGE=dir`]: cli.md#node_v8_coveragedir +[`Object.freeze()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze [`SourceMap`]: #class-modulesourcemap [`initialize`]: #initialize [`module.constants.compileCacheStatus`]: #moduleconstantscompilecachestatus diff --git a/lib/internal/source_map/source_map.js b/lib/internal/source_map/source_map.js index dbfc05e8925d46..42e7bca3c4c5c0 100644 --- a/lib/internal/source_map/source_map.js +++ b/lib/internal/source_map/source_map.js @@ -71,6 +71,7 @@ const { ArrayPrototypePush, ArrayPrototypeSlice, ArrayPrototypeSort, + ObjectFreeze, ObjectPrototypeHasOwnProperty, StringPrototypeCharAt, Symbol, @@ -144,7 +145,7 @@ class SourceMap { this.#payload = cloneSourceMapV3(payload); this.#parseMappingPayload(); if (ArrayIsArray(lineLengths) && lineLengths.length) { - this.#lineLengths = lineLengths; + this.#lineLengths = ObjectFreeze(ArrayPrototypeSlice(lineLengths)); } } @@ -152,7 +153,7 @@ class SourceMap { * @returns {object} raw source map v3 payload. */ get payload() { - return cloneSourceMapV3(this.#payload); + return this.#payload; } get [kMappings]() { @@ -163,10 +164,7 @@ class SourceMap { * @returns {number[] | undefined} line lengths of generated source code */ get lineLengths() { - if (this.#lineLengths) { - return ArrayPrototypeSlice(this.#lineLengths); - } - return undefined; + return this.#lineLengths; } #parseMappingPayload = () => { @@ -366,10 +364,10 @@ function cloneSourceMapV3(payload) { for (const key in payload) { if (ObjectPrototypeHasOwnProperty(payload, key) && ArrayIsArray(payload[key])) { - payload[key] = ArrayPrototypeSlice(payload[key]); + payload[key] = ObjectFreeze(ArrayPrototypeSlice(payload[key])); } } - return payload; + return ObjectFreeze(payload); } /** diff --git a/test/parallel/test-source-map-api.js b/test/parallel/test-source-map-api.js index 8c965891536072..bc09d2ca2b8775 100644 --- a/test/parallel/test-source-map-api.js +++ b/test/parallel/test-source-map-api.js @@ -140,6 +140,14 @@ const { readFileSync } = require('fs'); assert.notStrictEqual(payload, sourceMap.payload); assert.strictEqual(payload.sources[0], sourceMap.payload.sources[0]); assert.notStrictEqual(payload.sources, sourceMap.payload.sources); + // The payload and its arrays should be frozen to avoid unnecessary cloning: + assert(Object.isFrozen(sourceMap.payload)); + assert(Object.isFrozen(sourceMap.payload.sources)); + // The same frozen object is returned on each call: + assert.strictEqual(sourceMap.payload, sourceMap.payload); + // lineLengths should be frozen and return the same reference each call: + assert(Object.isFrozen(sourceMap.lineLengths)); + assert.strictEqual(sourceMap.lineLengths, sourceMap.lineLengths); } // findEntry() and findOrigin() must return empty object instead of @@ -178,6 +186,11 @@ const { readFileSync } = require('fs'); assert.notStrictEqual(payload, sourceMap.payload); assert.strictEqual(payload.sources[0], sourceMap.payload.sources[0]); assert.notStrictEqual(payload.sources, sourceMap.payload.sources); + // The payload and its arrays should be frozen to avoid unnecessary cloning: + assert(Object.isFrozen(sourceMap.payload)); + assert(Object.isFrozen(sourceMap.payload.sources)); + // The same frozen object is returned on each call: + assert.strictEqual(sourceMap.payload, sourceMap.payload); } // Test various known decodings to ensure decodeVLQ works correctly. From 0b5b1894267f154b4e6b4c75b0057a2331f1f0ef Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Tue, 19 May 2026 12:16:51 -0700 Subject: [PATCH 19/83] test: avoid repeated writes in watch helper Use performFileOperation() for test runner watch updates so the run() API path schedules a single delayed write instead of rewriting the file until the second run completes. Repeated writes can trigger another watch restart while the previous rerun is still active. The runner then terminates the in-flight child process with SIGTERM, which can make the captured output include both a failed file-level subtest and the next successful run. Also count only root summary duration lines when detecting completed runs. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5 PR-URL: https://github.com/nodejs/node/pull/63386 Refs: https://github.com/nodejs/reliability/blob/main/reports/2026-05-17.md#jstest-failure Reviewed-By: Antoine du Hamel Reviewed-By: Chemi Atlow --- test/common/watch.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/test/common/watch.js b/test/common/watch.js index 81defc49835eb1..c3d22c30f78e0c 100644 --- a/test/common/watch.js +++ b/test/common/watch.js @@ -106,7 +106,7 @@ async function testRunnerWatch({ child.stdout.on('data', (data) => { stdout += data.toString(); currentRun += data.toString(); - const testRuns = stdout.match(/duration_ms\s\d+/g); + const testRuns = stdout.match(/^\S+ duration_ms\s\d+/gm); if (testRuns?.length >= 1) ran1.resolve(); if (testRuns?.length >= 2) ran2.resolve(); }); @@ -118,18 +118,11 @@ async function testRunnerWatch({ const content = fixtureContent[fileToUpdate]; const path = fixturePaths[fileToUpdate]; - if (useRunApi) { - const interval = setInterval( - () => writeFileSync(path, content), - common.platformTimeout(1000), - ); - await ran2.promise; - clearInterval(interval); - } else { - writeFileSync(path, content); - await setTimeout(common.platformTimeout(1000)); - await ran2.promise; - } + await performFileOperation( + () => writeFileSync(path, content), + useRunApi, + ); + await ran2.promise; runs.push(currentRun); child.kill(); From 46e17c728e644ef0a8bc0703a3e0d60adbc2d057 Mon Sep 17 00:00:00 2001 From: Mike McCready <66998419+MikeMcC399@users.noreply.github.com> Date: Tue, 19 May 2026 22:00:55 +0200 Subject: [PATCH 20/83] build,win: add Rust toolchain automated configuration Windows Signed-off-by: Mike McCready <66998419+MikeMcC399@users.noreply.github.com> PR-URL: https://github.com/nodejs/node/pull/63381 Refs: https://github.com/nodejs/node/issues/63225 Refs: https://github.com/nodejs/node/pull/63367 Reviewed-By: Joyee Cheung Reviewed-By: Stefan Stojanovic Reviewed-By: Chengzhong Wu --- .configurations/configuration.dsc.yaml | 9 ++++++++- .configurations/configuration.vsBuildTools.dsc.yaml | 9 ++++++++- .configurations/configuration.vsEnterprise.dsc.yaml | 9 ++++++++- .configurations/configuration.vsProfessional.dsc.yaml | 9 ++++++++- BUILDING.md | 1 + 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/.configurations/configuration.dsc.yaml b/.configurations/configuration.dsc.yaml index 9e38aaba78a412..8c637d7dae819a 100644 --- a/.configurations/configuration.dsc.yaml +++ b/.configurations/configuration.dsc.yaml @@ -35,6 +35,13 @@ properties: - Microsoft.VisualStudio.Workload.NativeDesktop - Microsoft.VisualStudio.Component.VC.Llvm.Clang - Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset + - resource: Microsoft.WinGet.DSC/WinGetPackage + id: rustPackage + directives: + description: Install Rust with MSVC toolchain + settings: + id: Rustlang.Rust.MSVC + source: winget - resource: Microsoft.WinGet.DSC/WinGetPackage id: gitPackage directives: @@ -51,4 +58,4 @@ properties: settings: id: Nasm.Nasm source: winget - configurationVersion: 0.1.1 + configurationVersion: 0.2.0 diff --git a/.configurations/configuration.vsBuildTools.dsc.yaml b/.configurations/configuration.vsBuildTools.dsc.yaml index 5434b44b3e0459..3e3a51ca90260f 100644 --- a/.configurations/configuration.vsBuildTools.dsc.yaml +++ b/.configurations/configuration.vsBuildTools.dsc.yaml @@ -35,6 +35,13 @@ properties: - Microsoft.VisualStudio.Workload.VCTools - Microsoft.VisualStudio.Component.VC.Llvm.Clang - Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset + - resource: Microsoft.WinGet.DSC/WinGetPackage + id: rustPackage + directives: + description: Install Rust with MSVC toolchain + settings: + id: Rustlang.Rust.MSVC + source: winget - resource: Microsoft.WinGet.DSC/WinGetPackage id: gitPackage directives: @@ -51,4 +58,4 @@ properties: settings: id: Nasm.Nasm source: winget - configurationVersion: 0.1.1 + configurationVersion: 0.2.0 diff --git a/.configurations/configuration.vsEnterprise.dsc.yaml b/.configurations/configuration.vsEnterprise.dsc.yaml index 4faf7d77d371d6..124a391b7843fa 100644 --- a/.configurations/configuration.vsEnterprise.dsc.yaml +++ b/.configurations/configuration.vsEnterprise.dsc.yaml @@ -35,6 +35,13 @@ properties: - Microsoft.VisualStudio.Workload.NativeDesktop - Microsoft.VisualStudio.Component.VC.Llvm.Clang - Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset + - resource: Microsoft.WinGet.DSC/WinGetPackage + id: rustPackage + directives: + description: Install Rust with MSVC toolchain + settings: + id: Rustlang.Rust.MSVC + source: winget - resource: Microsoft.WinGet.DSC/WinGetPackage id: gitPackage directives: @@ -51,4 +58,4 @@ properties: settings: id: Nasm.Nasm source: winget - configurationVersion: 0.1.1 + configurationVersion: 0.2.0 diff --git a/.configurations/configuration.vsProfessional.dsc.yaml b/.configurations/configuration.vsProfessional.dsc.yaml index e094059e826c0e..7d2a8b36984ccf 100644 --- a/.configurations/configuration.vsProfessional.dsc.yaml +++ b/.configurations/configuration.vsProfessional.dsc.yaml @@ -35,6 +35,13 @@ properties: - Microsoft.VisualStudio.Workload.NativeDesktop - Microsoft.VisualStudio.Component.VC.Llvm.Clang - Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset + - resource: Microsoft.WinGet.DSC/WinGetPackage + id: rustPackage + directives: + description: Install Rust with MSVC toolchain + settings: + id: Rustlang.Rust.MSVC + source: winget - resource: Microsoft.WinGet.DSC/WinGetPackage id: gitPackage directives: @@ -51,4 +58,4 @@ properties: settings: id: Nasm.Nasm source: winget - configurationVersion: 0.1.1 + configurationVersion: 0.2.0 diff --git a/BUILDING.md b/BUILDING.md index 5cf5e9f57d6753..d70f084783d527 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -796,6 +796,7 @@ easily. These files will install the following * `Python 3.14` * `Visual Studio 2022` (Build Tools, Community, Professional or Enterprise Edition) and "Desktop development with C++" workload, Clang and ClangToolset optional components +* `Rust Toolchain MSVC` * `NetWide Assembler` The following Desired State Configuration (DSC) files are available: From 5605f6bca4bec6146af5bf678e44403df41cae91 Mon Sep 17 00:00:00 2001 From: YuSheng Chen Date: Wed, 20 May 2026 06:57:05 +0800 Subject: [PATCH 21/83] doc: update http2's `push` and `trailers` events with `rawHeaders` param Signed-off-by: Yu-Sheng Chen PR-URL: https://github.com/nodejs/node/pull/63259 Reviewed-By: Tim Perry Reviewed-By: Luigi Pinca --- doc/api/http2.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/api/http2.md b/doc/api/http2.md index b179743d85a121..ff717b93fdecac 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -1341,10 +1341,11 @@ added: v8.4.0 * `headers` {HTTP/2 Headers Object} An object describing the headers * `flags` {number} The associated numeric flags +* `rawHeaders` {HTTP/2 Raw Headers} The `'trailers'` event is emitted when a block of headers associated with -trailing header fields is received. The listener callback is passed the -[HTTP/2 Headers Object][] and flags associated with the headers. +trailing header fields is received. The listener callback is passed the [HTTP/2 Headers Object][], flags associated +with the headers, and the headers in raw format (see [HTTP/2 Raw Headers][]). This event might not be emitted if `http2stream.end()` is called before trailers are received and the incoming data is not being read or @@ -1704,10 +1705,11 @@ added: v8.4.0 * `headers` {HTTP/2 Headers Object} * `flags` {number} +* `rawHeaders` {HTTP/2 Raw Headers} The `'push'` event is emitted when response headers for a Server Push stream -are received. The listener callback is passed the [HTTP/2 Headers Object][] and -flags associated with the headers. +are received. The listener callback is passed the [HTTP/2 Headers Object][], flags associated +with the headers, and the headers in raw format (see [HTTP/2 Raw Headers][]). ```js stream.on('push', (headers, flags) => { From 4f4077a299f1d2d42d35b89edd34216a4411819a Mon Sep 17 00:00:00 2001 From: Claudio Wunder Date: Tue, 19 May 2026 20:02:54 -0300 Subject: [PATCH 22/83] doc: remove the bi-monthly contributor spotlight section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/62734 Reviewed-By: Luigi Pinca Reviewed-By: Michaël Zasso Reviewed-By: Matteo Collina --- doc/contributing/recognizing-contributors.md | 26 -------------------- 1 file changed, 26 deletions(-) diff --git a/doc/contributing/recognizing-contributors.md b/doc/contributing/recognizing-contributors.md index c0bf37247e3121..f79bd8dd2c55ca 100644 --- a/doc/contributing/recognizing-contributors.md +++ b/doc/contributing/recognizing-contributors.md @@ -49,29 +49,3 @@ making a request in the #nodejs-social channel in the OpenJS Foundation slack. We trust that collaborators will only request amplification when they believe the event is relevant to the Node.js community and the content of the post is in line with the norms of the project. - -## Bi-monthly contributor spotlight - -The contributor spotlight program showcases individual(s) or teams who have -made signification contributions to the project. Anybody who is not -a member of the Technical Steering Committee (TSC) and has made a -notable contribution to the project can be nominated. They DO NOT need -to be a collaborator, team member etc. - -The work of the team or individual(s) will be showcased on the -Node.js social channels and, if warranted, through a blog post created by the -OpenJS marketing staff along with the team or individual(s) which will -be published on [openjsf.org](https://openjsf.org/). - -Nominations can be made through this web form: -[Contributor Spotlight nomination](https://forms.gle/dXBXZn8yu83HLJ57A) - -Nominations will be reviewed/approved by the Technical Steering Committee (TSC) -on a regular basis as scheduled by the TSC chair. The TSC will also -recommend the order in which approved nominations are processed -by the OpenJS marketing staff. - -Before any work proceeds on an approved nomination the individual(s) -or team will be contacted to confirm they want to participate. Social -content and or spotlight blog post will only be published after the -team or individual(s) have confirmed they are happy with the content. From 0c7034f5aef0095254af484312322a6dc2cef02e Mon Sep 17 00:00:00 2001 From: joao-oliveira-softtor Date: Tue, 19 May 2026 20:19:36 -0300 Subject: [PATCH 23/83] doc: fix article usage before vowel-sound acronyms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several prose references to HTTP, HTTPS, SSL, HPE_HEADER_OVERFLOW and ECMAScript used the article "a" where the acronym starts with a vowel sound and should take "an". The rule is based on pronunciation, not spelling: HTTP is read "aitch-tee-tee-pee", SSL is read "ess-es-el", ECMAScript is read "ek-mah-script", and HPE is read "aitch-pee-ee" — all starting with a vowel sound. Affected files: * doc/api/crypto.md — "disable a SSL 3.0/TLS 1.0 vulnerability" * doc/api/http.md — five occurrences ("a HTTP '400 Bad Request'", "a HTTP '431 Request Header Fields Too Large'", "a HTTP/1.1 102 Processing message", two copies of "use a HTTP parser") plus two references to "a HPE_HEADER_OVERFLOW" * doc/api/http2.md — two code-sample comments reading "// Detects if it is a HTTPS request or HTTP/2" * doc/api/module.md — "compiles a CommonJS, a ECMAScript Module, or a TypeScript module" (only the middle article changes; the adjacent "a CommonJS" and "a TypeScript" are both correct) * doc/api/tls.md — two references to "part of a SSL/TLS handshake" in tlsSocket.getFinished() and tlsSocket.getPeerFinished() No behavior changes, documentation only. Signed-off-by: João Victor Oliveira PR-URL: https://github.com/nodejs/node/pull/62696 Reviewed-By: Aviv Keller Reviewed-By: Luigi Pinca Reviewed-By: Akhil Marsonya Reviewed-By: Jacob Smith --- doc/api/crypto.md | 2 +- doc/api/http.md | 12 ++++++------ doc/api/http2.md | 4 ++-- doc/api/module.md | 2 +- doc/api/tls.md | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index adaf8f64b56733..efb3fa4a6cf0ee 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -6657,7 +6657,7 @@ See the [list of SSL OP Flags][] for details. SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS - Instructs OpenSSL to disable a SSL 3.0/TLS 1.0 vulnerability + Instructs OpenSSL to disable an SSL 3.0/TLS 1.0 vulnerability workaround added in OpenSSL 0.9.6d. diff --git a/doc/api/http.md b/doc/api/http.md index a916337287e109..3daf37737d0c2a 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -1516,7 +1516,7 @@ changes: - version: v12.0.0 pr-url: https://github.com/nodejs/node/pull/25605 description: The default behavior will return a 431 Request Header - Fields Too Large if a HPE_HEADER_OVERFLOW error occurs. + Fields Too Large if an HPE_HEADER_OVERFLOW error occurs. - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/17672 description: The `rawPacket` is the current buffer that just parsed. Adding @@ -1542,8 +1542,8 @@ This event is guaranteed to be passed an instance of the {net.Socket} class, a subclass of {stream.Duplex}, unless the user specifies a socket type other than {net.Socket}. -Default behavior is to try close the socket with a HTTP '400 Bad Request', -or a HTTP '431 Request Header Fields Too Large' in the case of a +Default behavior is to try close the socket with an HTTP '400 Bad Request', +or an HTTP '431 Request Header Fields Too Large' in the case of an [`HPE_HEADER_OVERFLOW`][] error. If the socket is not writable or headers of the current attached [`http.ServerResponse`][] has been sent, it is immediately destroyed. @@ -2735,7 +2735,7 @@ response.writeInformation(110, { 'X-Progress': '50%' }); added: v10.0.0 --> -Sends a HTTP/1.1 102 Processing message to the client, indicating that +Sends an HTTP/1.1 102 Processing message to the client, indicating that the request body should be sent. ## Class: `http.IncomingMessage` @@ -3734,7 +3734,7 @@ changes: `readableHighWaterMark` and `writableHighWaterMark`. This affects `highWaterMark` property of both `IncomingMessage` and `ServerResponse`. **Default:** See [`stream.getDefaultHighWaterMark()`][]. - * `insecureHTTPParser` {boolean} If set to `true`, it will use a HTTP parser + * `insecureHTTPParser` {boolean} If set to `true`, it will use an HTTP parser with leniency flags enabled. Using the insecure parser should be avoided. See [`--insecure-http-parser`][] for more information. **Default:** `false`. @@ -4045,7 +4045,7 @@ changes: request to. **Default:** `'localhost'`. * `hostname` {string} Alias for `host`. To support [`url.parse()`][], `hostname` will be used if both `host` and `hostname` are specified. - * `insecureHTTPParser` {boolean} If set to `true`, it will use a HTTP parser + * `insecureHTTPParser` {boolean} If set to `true`, it will use an HTTP parser with leniency flags enabled. Using the insecure parser should be avoided. See [`--insecure-http-parser`][] for more information. **Default:** `false` diff --git a/doc/api/http2.md b/doc/api/http2.md index ff717b93fdecac..fff90abe41fde6 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -3976,7 +3976,7 @@ const server = createSecureServer( ).listen(8000); function onRequest(req, res) { - // Detects if it is a HTTPS request or HTTP/2 + // Detects if it is an HTTPS request or HTTP/2 const { socket: { alpnProtocol } } = req.httpVersion === '2.0' ? req.stream.session : req; res.writeHead(200, { 'content-type': 'application/json' }); @@ -4000,7 +4000,7 @@ const server = createSecureServer( ).listen(4443); function onRequest(req, res) { - // Detects if it is a HTTPS request or HTTP/2 + // Detects if it is an HTTPS request or HTTP/2 const { socket: { alpnProtocol } } = req.httpVersion === '2.0' ? req.stream.session : req; res.writeHead(200, { 'content-type': 'application/json' }); diff --git a/doc/api/module.md b/doc/api/module.md index 451c8b3348a47a..62780536914f96 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -366,7 +366,7 @@ changes: The module compile cache can be enabled either using the [`module.enableCompileCache()`][] method or the [`NODE_COMPILE_CACHE=dir`][] environment variable. After it is enabled, -whenever Node.js compiles a CommonJS, a ECMAScript Module, or a TypeScript module, it will +whenever Node.js compiles a CommonJS, an ECMAScript Module, or a TypeScript module, it will use on-disk [V8 code cache][] persisted in the specified directory to speed up the compilation. This may slow down the first load of a module graph, but subsequent loads of the same module graph may get a significant speedup if the contents of the modules do not change. diff --git a/doc/api/tls.md b/doc/api/tls.md index dc4719d391d003..5d11e2c53eada0 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -1212,7 +1212,7 @@ added: v9.9.0 --> * Returns: {Buffer|undefined} The latest `Finished` message that has been - sent to the socket as part of a SSL/TLS handshake, or `undefined` if + sent to the socket as part of an SSL/TLS handshake, or `undefined` if no `Finished` message has been sent yet. As the `Finished` messages are message digests of the complete handshake @@ -1355,7 +1355,7 @@ added: v9.9.0 --> * Returns: {Buffer|undefined} The latest `Finished` message that is expected - or has actually been received from the socket as part of a SSL/TLS handshake, + or has actually been received from the socket as part of an SSL/TLS handshake, or `undefined` if there is no `Finished` message so far. As the `Finished` messages are message digests of the complete handshake From f8685431d34cc3495af5cc8682011b1313b812dc Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Tue, 19 May 2026 17:15:34 -0700 Subject: [PATCH 24/83] test: deflake connection refused proxy tests Use 127.0.0.1:10, matching existing refused-connection tests, instead of binding and releasing an ephemeral port that can be reused before the child process connects. Clear NO_PROXY and no_proxy so local proxy bypass settings do not skip the proxy connection attempt. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5 PR-URL: https://github.com/nodejs/node/pull/63395 Refs: https://github.com/nodejs/reliability/blob/main/reports/2026-05-15.md#jstest-failure Reviewed-By: Joyee Cheung Reviewed-By: Luigi Pinca --- ...-http-proxy-request-connection-refused.mjs | 37 +++++----------- ...https-proxy-request-connection-refused.mjs | 42 ++++++------------- 2 files changed, 24 insertions(+), 55 deletions(-) diff --git a/test/client-proxy/test-http-proxy-request-connection-refused.mjs b/test/client-proxy/test-http-proxy-request-connection-refused.mjs index d07cf8ce530203..bf8fe9baff27f5 100644 --- a/test/client-proxy/test-http-proxy-request-connection-refused.mjs +++ b/test/client-proxy/test-http-proxy-request-connection-refused.mjs @@ -15,34 +15,19 @@ await once(server, 'listening'); const serverHost = `localhost:${server.address().port}`; const requestUrl = `http://${serverHost}/test`; -let maxRetries = 10; let foundRefused = false; -while (maxRetries-- > 0) { - // Make it fail on connection refused by connecting to a port of a closed server. - // If it succeeds, get a different port and retry. - const proxy = http.createServer((req, res) => { - res.destroy(); - }); - proxy.listen(0); - await once(proxy, 'listening'); - const port = proxy.address().port; - proxy.close(); - await once(proxy, 'close'); +const port = 10; +console.log(`Trying proxy at port ${port}`); +const { stderr } = await runProxiedRequest({ + NODE_USE_ENV_PROXY: 1, + REQUEST_URL: requestUrl, + HTTP_PROXY: `http://127.0.0.1:${port}`, + NO_PROXY: '', + no_proxy: '', + REQUEST_TIMEOUT: 5000, +}); - console.log(`Trying proxy at port ${port}`); - const { stderr } = await runProxiedRequest({ - NODE_USE_ENV_PROXY: 1, - REQUEST_URL: requestUrl, - HTTP_PROXY: `http://localhost:${port}`, - REQUEST_TIMEOUT: 5000, - }); - - foundRefused = /Error.*connect ECONNREFUSED/.test(stderr); - if (foundRefused) { - // The proxy client should get a connection refused error. - break; - } -} +foundRefused = /Error.*connect ECONNREFUSED/.test(stderr); server.close(); assert(foundRefused, 'Expected ECONNREFUSED error from proxy request'); diff --git a/test/client-proxy/test-https-proxy-request-connection-refused.mjs b/test/client-proxy/test-https-proxy-request-connection-refused.mjs index f2a9875a4ef44a..f1c0de89ba957a 100644 --- a/test/client-proxy/test-https-proxy-request-connection-refused.mjs +++ b/test/client-proxy/test-https-proxy-request-connection-refused.mjs @@ -5,7 +5,6 @@ import fixtures from '../common/fixtures.js'; import assert from 'node:assert'; import { once } from 'events'; import { runProxiedRequest } from '../common/proxy-server.js'; -import http from 'node:http'; if (!common.hasCrypto) common.skip('missing crypto'); @@ -25,35 +24,20 @@ await once(server, 'listening'); const serverHost = `localhost:${server.address().port}`; const requestUrl = `https://${serverHost}/test`; -let maxRetries = 10; let foundRefused = false; -while (maxRetries-- > 0) { - // Make it fail on connection refused by connecting to a port of a closed server. - // If it succeeds, get a different port and retry. - const proxy = http.createServer((req, res) => { - res.destroy(); - }); - proxy.listen(0); - await once(proxy, 'listening'); - const port = proxy.address().port; - proxy.close(); - await once(proxy, 'close'); - - console.log(`Trying proxy at port ${port}`); - const { stderr } = await runProxiedRequest({ - NODE_USE_ENV_PROXY: 1, - REQUEST_URL: requestUrl, - HTTPS_PROXY: `http://localhost:${port}`, - NODE_EXTRA_CA_CERTS: fixtures.path('keys', 'fake-startcom-root-cert.pem'), - REQUEST_TIMEOUT: 5000, - }); - - foundRefused = /Error.*connect ECONNREFUSED/.test(stderr); - if (foundRefused) { - // The proxy client should get a connection refused error. - break; - } -} +const port = 10; +console.log(`Trying proxy at port ${port}`); +const { stderr } = await runProxiedRequest({ + NODE_USE_ENV_PROXY: 1, + REQUEST_URL: requestUrl, + HTTPS_PROXY: `http://127.0.0.1:${port}`, + NO_PROXY: '', + no_proxy: '', + NODE_EXTRA_CA_CERTS: fixtures.path('keys', 'fake-startcom-root-cert.pem'), + REQUEST_TIMEOUT: 5000, +}); + +foundRefused = /Error.*connect ECONNREFUSED/.test(stderr); server.close(); assert(foundRefused, 'Expected ECONNREFUSED error from proxy request'); From 0e8fb913d857b0d4123995e401293a0c9ee5efd8 Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Tue, 19 May 2026 20:26:58 -0700 Subject: [PATCH 25/83] test: disable Maglev in near-heap-limit worker test The test expects the worker to run out of memory during startup while creating the message port. With Maglev enabled, the tiny worker heap can be exhausted earlier while generating deoptimization data, which changes the failure mode. Disable Maglev so the induced OOM reaches the path covered by the test. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5 PR-URL: https://github.com/nodejs/node/pull/63398 Refs: https://github.com/nodejs/reliability/blob/main/reports/2026-05-18.md#jstest-failure Reviewed-By: Antoine du Hamel Reviewed-By: Luigi Pinca Reviewed-By: Richard Lau --- test/parallel/test-worker-nearheaplimit-deadlock.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-worker-nearheaplimit-deadlock.js b/test/parallel/test-worker-nearheaplimit-deadlock.js index b22c86b211611f..b7f19f6089e88c 100644 --- a/test/parallel/test-worker-nearheaplimit-deadlock.js +++ b/test/parallel/test-worker-nearheaplimit-deadlock.js @@ -1,7 +1,9 @@ -// Flags: --no-node-snapshot +// Flags: --no-node-snapshot --no-maglev // With node snapshot the OOM can occur during the deserialization of the // context, so disable it since we want the OOM to occur during the creation of // the message port. +// With Maglev, the OOM can occur during compilation instead, so disable it for +// the same reason. 'use strict'; const common = require('../common'); const assert = require('assert'); From 09b369fd46493e5af11ece5dfe26a065c4ddd917 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Wed, 20 May 2026 03:40:57 -0400 Subject: [PATCH 26/83] meta: move one or more collaborators to emeritus PR-URL: https://github.com/nodejs/node/pull/63402 Reviewed-By: Moshe Atlow Reviewed-By: Debadree Chatterjee Reviewed-By: Luigi Pinca Reviewed-By: Antoine du Hamel --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 55f15c5a8045dc..c2012523eb199a 100644 --- a/README.md +++ b/README.md @@ -317,8 +317,6 @@ For information about the governance of the Node.js project, see **Daeyeon Jeong** <> (he/him) * [dario-piotrowicz](https://github.com/dario-piotrowicz) - **Dario Piotrowicz** <> (he/him) -* [debadree25](https://github.com/debadree25) - - **Debadree Chatterjee** <> (he/him) * [deokjinkim](https://github.com/deokjinkim) - **Deokjin Kim** <> (he/him) * [edsadr](https://github.com/edsadr) - @@ -365,8 +363,6 @@ For information about the governance of the Node.js project, see **James M Snell** <> (he/him) * [jazelly](https://github.com/jazelly) - **Jason Zhang** <> (he/him) -* [JonasBa](https://github.com/JonasBa) - - **Jonas Badalic** <> (he/him) * [joyeecheung](https://github.com/joyeecheung) - **Joyee Cheung** <> (she/her) * [juanarbol](https://github.com/juanarbol) - @@ -507,6 +503,8 @@ For information about the governance of the Node.js project, see **David Cai** <> (he/him) * [davisjam](https://github.com/davisjam) - **Jamie Davis** <> (he/him) +* [debadree25](https://github.com/debadree25) - + **Debadree Chatterjee** <> (he/him) * [devnexen](https://github.com/devnexen) - **David Carlier** <> * [devsnek](https://github.com/devsnek) - @@ -571,6 +569,8 @@ For information about the governance of the Node.js project, see **João Reis** <> * [joesepi](https://github.com/joesepi) - **Joe Sepi** <> (he/him) +* [JonasBa](https://github.com/JonasBa) - + **Jonas Badalic** <> (he/him) * [joshgav](https://github.com/joshgav) - **Josh Gavant** <> * [julianduque](https://github.com/julianduque) - From 701f73589b03d9101f14af63d4b0198691105526 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 20 May 2026 09:55:01 +0200 Subject: [PATCH 27/83] doc: fix promise nomenclature in `stream_iter.md` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Antoine du Hamel PR-URL: https://github.com/nodejs/node/pull/63406 Reviewed-By: René Reviewed-By: Luigi Pinca --- doc/api/fs.md | 16 ++++++++-------- doc/api/stream_iter.md | 36 ++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 884e5935219b67..56291efa8a1971 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -1034,16 +1034,16 @@ added: Set this to match the reader's `chunkSize` for optimal `pipeTo()` performance. **Default:** `131072` (128 KB). * Returns: {Object} - * `write(chunk[, options])` {Function} Returns {Promise\}. + * `write(chunk[, options])` {Function} Returns {Promise}. Accepts `Uint8Array`, `Buffer`, or string (UTF-8 encoded). * `chunk` {Buffer|TypedArray|DataView|string} * `options` {Object} * `signal` {AbortSignal} If the signal is already aborted, the write rejects with `AbortError` without performing I/O. - * `writev(chunks[, options])` {Function} Returns {Promise\}. Uses + * `writev(chunks[, options])` {Function} Returns {Promise}. Uses scatter/gather I/O via a single `writev()` syscall. Accepts mixed `Uint8Array`/string arrays. - * `chunks` {Array\} + * `chunks` {Buffer\[]|TypedArray\[]|DataView\[]|string\[]} * `options` {Object} * `signal` {AbortSignal} If the signal is already aborted, the write rejects with `AbortError` without performing I/O. @@ -1055,10 +1055,10 @@ added: * `chunk` {Buffer|TypedArray|DataView|string} * `writevSync(chunks)` {Function} Returns {boolean}. Synchronous batch write. Same fallback semantics as `writeSync()`. - * `chunks` {Array\} - * `end([options])` {Function} Returns {Promise\} total bytes - written. Idempotent: returns `totalBytesWritten` if already closed, - returns the pending promise if already closing. Rejects if the writer + * `chunks` {Buffer\[]|TypedArray\[]|DataView\[]|string\[]} + * `end([options])` {Function} Returns {Promise}, fulfills with the total + number of bytes written. Idempotent: returns `totalBytesWritten` if already + closed, returns the pending promise if already closing. Rejects if the writer is in an errored state. * `options` {Object} * `signal` {AbortSignal} If the signal is already aborted, `end()` @@ -2815,7 +2815,7 @@ changes: * `filter` {Function} Function to filter copied files/directories. Return `true` to copy the item, `false` to ignore it. When ignoring a directory, all of its contents will be skipped as well. Can also return a `Promise` - that resolves to `true` or `false` **Default:** `undefined`. + that fulfills with `true` or `false`. **Default:** `undefined`. * `src` {string} source path to copy. * `dest` {string} destination path to copy to. * Returns: {boolean|Promise} A value that is coercible to `boolean` or diff --git a/doc/api/stream_iter.md b/doc/api/stream_iter.md index 611f1bf88c7c02..ab4915cc76b247 100644 --- a/doc/api/stream_iter.md +++ b/doc/api/stream_iter.md @@ -220,7 +220,7 @@ that closes when the bucket is full: * **Pending writes (the hose)** -- writes waiting for slot space. After the consumer drains, pending writes are promoted into the now-empty - slots and their promises resolve. + slots and their promises settle. How each policy uses these buffers: @@ -430,7 +430,7 @@ The value is always non-negative. * `options` {Object} * `signal` {AbortSignal} Cancel just this operation. The signal cancels only the pending `end()` call; it does not fail the writer itself. -* Returns: {Promise\} Total bytes written. +* Returns: {Promise} Fulfills with the total number of bytes written. Signal that no more data will be written. @@ -463,9 +463,9 @@ transition with no async work to perform. * `options` {Object} * `signal` {AbortSignal} Cancel just this write operation. The signal cancels only the pending `write()` call; it does not fail the writer itself. -* Returns: {Promise\} +* Returns: {Promise} Fulfills with `undefined` when buffer space is available. -Write a chunk. The promise resolves when buffer space is available. +Write a chunk. #### `writer.writeSync(chunk)` @@ -481,7 +481,7 @@ Synchronous write. Does not block; returns `false` if backpressure is active. * `options` {Object} * `signal` {AbortSignal} Cancel just this write operation. The signal cancels only the pending `writev()` call; it does not fail the writer itself. -* Returns: {Promise\} +* Returns: {Promise} Write multiple chunks as a single batch. @@ -606,7 +606,7 @@ added: the source ends. **Default:** `false`. * `preventFail` {boolean} If `true`, do not call `writer.fail()` on error. **Default:** `false`. -* Returns: {Promise\} Total bytes written. +* Returns: {Promise} Fulfills with the total number of bytes written. Pipe a source through transforms into a writer. If the writer has a `writev(chunks)` method, entire batches are passed in a single call (enabling @@ -912,7 +912,7 @@ added: * `signal` {AbortSignal} * `limit` {number} Maximum number of bytes to consume. If the total bytes collected exceeds limit, an `ERR_OUT_OF_RANGE` error is thrown -* Returns: {Promise\} +* Returns: {Promise} Fulfills with an array of `Uint8Array` objects. Collect all chunks as an array of `Uint8Array` values (without concatenating). @@ -928,7 +928,7 @@ added: * `signal` {AbortSignal} * `limit` {number} Maximum number of bytes to consume. If the total bytes collected exceeds limit, an `ERR_OUT_OF_RANGE` error is thrown -* Returns: {Promise\} +* Returns: {Promise} Fulfills with an `ArrayBuffer` object. Collect all bytes into an `ArrayBuffer`. @@ -974,7 +974,7 @@ added: * `signal` {AbortSignal} * `limit` {number} Maximum number of bytes to consume. If the total bytes collected exceeds limit, an `ERR_OUT_OF_RANGE` error is thrown -* Returns: {Promise\} +* Returns: {Promise} Fulfills with an `Uint8Array` object. Collect all bytes from a stream into a single `Uint8Array`. @@ -1024,7 +1024,7 @@ added: * `signal` {AbortSignal} * `limit` {number} Maximum number of bytes to consume. If the total bytes collected exceeds limit, an `ERR_OUT_OF_RANGE` error is thrown -* Returns: {Promise\} +* Returns: {Promise} Fulfills with a `string`. Collect all bytes and decode as text. @@ -1070,11 +1070,11 @@ added: --> * `drainable` {Object} An object implementing the drainable protocol. -* Returns: {Promise\|null} +* Returns: {Promise|null} -Wait for a drainable writer's backpressure to clear. Returns a promise that -resolves to `true` when the writer can accept more data, or `null` if the -object does not implement the drainable protocol. +Wait for a drainable writer's backpressure to clear. Returns `null` if +the object does not implement the drainable protocol, or a promise that +fulfills with `true` when the writer can accept more data. ```mjs import { push, ondrain, text } from 'node:stream/iter'; @@ -1794,8 +1794,8 @@ text(consumer).then(console.log); // 'hello' * Value: `Symbol.for('Stream.drainableProtocol')` Implement to make a writer compatible with `ondrain()`. The method should -return a promise that resolves when backpressure clears, or `null` if no -backpressure. +return `null` if no backpressure, or a promise that fulfills with a truthy value +when backpressure clears. ```mjs import { ondrain } from 'node:stream/iter'; @@ -2001,8 +2001,8 @@ console.log(textSync(consumer)); // 'hello' The value must be a function that converts the object into a streamable value. When the object is encountered anywhere in the streaming pipeline (as a source passed to `from()`, or as a value returned from a transform), this method is -called to produce the actual data. It may return (or resolve to) any streamable -value: a string, `Uint8Array`, `AsyncIterable`, `Iterable`, or another streamable +called to produce the actual data. It may return any value that resolves to: +a string, `Uint8Array`, `AsyncIterable`, `Iterable`, or another streamable object. ```mjs From 59e8484abd311a4cc97c779c04903c6573d12765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9?= Date: Wed, 20 May 2026 08:56:21 +0100 Subject: [PATCH 28/83] doc: remove unsupported template type from v8.md Signed-off-by: Renegade334 PR-URL: https://github.com/nodejs/node/pull/63410 Reviewed-By: Antoine du Hamel Reviewed-By: Chengzhong Wu Reviewed-By: Luigi Pinca --- doc/api/v8.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/v8.md b/doc/api/v8.md index fee6b067596fde..cf8777db973425 100644 --- a/doc/api/v8.md +++ b/doc/api/v8.md @@ -389,7 +389,7 @@ changes: * `format` {string} If it's `'count'`, the count of matched objects is returned. If it's `'summary'`, an array with summary strings of the matched objects is returned. -* Returns: {number|Array} +* Returns: {number|string\[]} This is similar to the [`queryObjects()` console API][] provided by the Chromium DevTools console. It can be used to search for objects that From d9558968d9f4c442d83fa2848e0d9e06e4a37489 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 20 May 2026 10:00:45 +0200 Subject: [PATCH 29/83] 2026-05-20, Version 26.2.0 (Current) Notable changes: doc: * mark `stream.compose` stable (Matteo Collina) https://github.com/nodejs/node/pull/62562 fs: * (SEMVER-MINOR) add `Temporal.Instant` support to `Stats` and `BigIntStats` (Livia Medeiros) https://github.com/nodejs/node/pull/60789 http: * (SEMVER-MINOR) add `writeInformation` to send arbitrary 1xx status codes (Tim Perry) https://github.com/nodejs/node/pull/63155 PR-URL: https://github.com/nodejs/node/pull/63440 --- CHANGELOG.md | 3 +- doc/api/cli.md | 2 +- doc/api/debugger.md | 2 +- doc/api/deprecations.md | 2 +- doc/api/errors.md | 6 +- doc/api/fs.md | 2 +- doc/api/http.md | 2 +- doc/api/http2.md | 2 +- doc/api/n-api.md | 2 +- doc/api/quic.md | 142 ++++++++++++++++---------------- doc/api/stream.md | 2 +- doc/api/test.md | 10 +-- doc/changelogs/CHANGELOG_V26.md | 128 ++++++++++++++++++++++++++++ 13 files changed, 217 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 984419475dbd2e..c20d0ea446bf2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,7 +42,8 @@ release. -26.1.0
+26.2.0
+26.1.0
26.0.0
diff --git a/doc/api/cli.md b/doc/api/cli.md index 8f7d6185ac464c..f544e0a0d68881 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -1416,7 +1416,7 @@ This feature requires `--allow-worker` if used with the [Permission Model][]. ### `--experimental-test-tag-filter=` > Stability: 1.0 - Early development diff --git a/doc/api/debugger.md b/doc/api/debugger.md index 0ac62b64dcc984..5eeffd43e57f5f 100644 --- a/doc/api/debugger.md +++ b/doc/api/debugger.md @@ -236,7 +236,7 @@ debug> added: - v26.1.0 changes: - - version: REPLACEME + - version: v26.2.0 pr-url: https://github.com/nodejs/node/pull/63286 description: JSON report schema bumped to v2. Probe `target` is now `{ suffix, line, column? }` instead of an array. Each "hit" event carries a diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 68dd5a4a36561c..6e4f4de2f144a7 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -4562,7 +4562,7 @@ removed in a future version of Node.js. diff --git a/doc/api/errors.md b/doc/api/errors.md index 8e0956c29f3843..e8c87ebb502fdc 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -2470,7 +2470,7 @@ compiled with ICU support. ### `ERR_NO_TEMPORAL` An attempt was made to use features that require [`Temporal`][], but Node.js was not @@ -2668,7 +2668,7 @@ Opening a QUIC stream failed. ### `ERR_QUIC_STREAM_ABORTED` > Stability: 1 - Experimental @@ -2681,7 +2681,7 @@ or session with an explicit application or transport error code. ### `ERR_QUIC_STREAM_RESET` > Stability: 1 - Experimental diff --git a/doc/api/fs.md b/doc/api/fs.md index 56291efa8a1971..e1211e4cd25f3f 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -7533,7 +7533,7 @@ i.e. before the `'ready'` event is emitted. * `statusCode` {number} An HTTP 1xx informational status code, between `100` diff --git a/doc/api/http2.md b/doc/api/http2.md index fff90abe41fde6..63a86ddc538887 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -4851,7 +4851,7 @@ response.writeEarlyHints({ #### `response.writeInformation(statusCode[, headers])` * `statusCode` {number} An HTTP 1xx informational status code, between `100` diff --git a/doc/api/n-api.md b/doc/api/n-api.md index d7e1c202c0ea89..29c0bff1fab712 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -2784,7 +2784,7 @@ Language Specification. added: v8.0.0 napiVersion: 1 changes: - - version: REPLACEME + - version: v26.2.0 pr-url: https://github.com/nodejs/node/pull/62710 description: Added support for `SharedArrayBuffer`. --> diff --git a/doc/api/quic.md b/doc/api/quic.md index ecd0d73803888a..4ad25810ab4627 100644 --- a/doc/api/quic.md +++ b/doc/api/quic.md @@ -403,7 +403,7 @@ a server once. ## `quic.constants` * {Object} @@ -541,7 +541,7 @@ True if `endpoint.destroy()` has been called. Read only. ### `endpoint.listening` * Type: {boolean} @@ -551,7 +551,7 @@ True if the endpoint is actively listening for incoming connections. Read only. ### `endpoint.maxConnectionsPerHost` * Type: {number} @@ -564,7 +564,7 @@ The valid range is `0` to `65535`. ### `endpoint.maxConnectionsTotal` * Type: {number} @@ -771,7 +771,7 @@ promise will reject with an `ERR_QUIC_TRANSPORT_ERROR` or ### `session.opened` * Type: {Promise} for an {Object} @@ -811,7 +811,7 @@ A promise that is fulfilled once the session is destroyed. ### `session.closing` * Type: {boolean} @@ -865,7 +865,7 @@ has been destroyed. Read only. ### `session.onerror` * Type: {Function|undefined} @@ -913,7 +913,7 @@ The callback to invoke when the status of a datagram is updated. Read/write. ### `session.onearlyrejected` * Type: {Function|undefined} @@ -970,7 +970,7 @@ The callback to invoke when the TLS handshake is completed. Read/write. ### `session.onnewtoken` * Type: {quic.OnNewTokenCallback} @@ -982,7 +982,7 @@ the same server to skip address validation. Read/write. ### `session.onorigin` * Type: {quic.OnOriginCallback} @@ -994,7 +994,7 @@ Read/write. ### `session.ongoaway` * Type: {Function} @@ -1019,7 +1019,7 @@ This callback is only relevant for HTTP/3 sessions. Read/write. ### `session.onkeylog` * Type: {quic.OnKeylogCallback} @@ -1035,7 +1035,7 @@ Can also be set via the `onkeylog` option in [`quic.connect()`][] or ### `session.onqlog` * Type: {quic.OnQlogCallback} @@ -1192,7 +1192,7 @@ what this endpoint advertises to the peer as its own maximum. ### `session.certificate` * Type: {Object|undefined} @@ -1204,7 +1204,7 @@ if the session is destroyed or no certificate is available. ### `session.peerCertificate` * Type: {Object|undefined} @@ -1216,7 +1216,7 @@ if the session is destroyed or the peer did not present a certificate. ### `session.ephemeralKeyInfo` * Type: {Object|undefined} @@ -1228,7 +1228,7 @@ The ephemeral key information for the session, with properties such as ### `session.maxDatagramSize` * Type: {number} @@ -1243,7 +1243,7 @@ will not be sent. ### `session.maxPendingDatagrams` * Type: {number} @@ -1480,7 +1480,7 @@ added: v23.8.0 ## Class: `QuicError` > Stability: 1 - Experimental @@ -1522,7 +1522,7 @@ the Node.js convention that `error.code` is a string. ### `new QuicError(message, options)` * `message` {string} A human-readable description of the error. @@ -1556,7 +1556,7 @@ console.log(custom.code); // 'ERR_MY_QUIC_FAILURE' ### `error.errorCode` * Type: {bigint} @@ -1566,7 +1566,7 @@ The numeric QUIC error code carried by this error. ### `error.type` * Type: {string} @@ -1599,7 +1599,7 @@ CONNECTION\_CLOSE with a non-zero error code). @@ -1678,7 +1678,7 @@ the implementation falls back to the negotiated application protocol's ### `stream.early` * Type: {boolean} @@ -1705,7 +1705,7 @@ or is still pending. Read only. ### `stream.highWaterMark` * Type: {number} @@ -1733,7 +1733,7 @@ pending. Read only. ### `stream.onerror` * Type: {Function|undefined} @@ -1780,7 +1780,7 @@ whole stream with [`stream.destroy()`][]. Read/write. ### `stream.headers` * Type: {Object|undefined} @@ -1797,7 +1797,7 @@ arrays. The object has `__proto__: null`. ### `stream.onheaders` * Type: {Function} @@ -1812,7 +1812,7 @@ Read/write. ### `stream.ontrailers` * Type: {Function} @@ -1825,7 +1825,7 @@ session that does not support headers. Read/write. ### `stream.oninfo` * Type: {Function} @@ -1840,7 +1840,7 @@ Read/write. ### `stream.onwanttrailers` * Type: {Function} @@ -1854,7 +1854,7 @@ Read/write. ### `stream.pendingTrailers` * Type: {Object|undefined} @@ -1868,7 +1868,7 @@ Read/write. ### `stream.sendHeaders(headers[, options])` * `headers` {Object} Header object with string keys and string or @@ -1886,7 +1886,7 @@ headers. Throws `ERR_INVALID_STATE` if the session does not support headers. ### `stream.sendInformationalHeaders(headers)` * `headers` {Object} Header object. Must include `:status` with a 1xx @@ -1899,7 +1899,7 @@ Sends informational (1xx) response headers. Server only. Throws ### `stream.sendTrailers(headers)` * `headers` {Object} Trailing header object. Pseudo-headers must not be @@ -1914,7 +1914,7 @@ does not support headers. ### `stream.priority` * Type: {Object|null} @@ -1933,7 +1933,7 @@ reflects the peer's requested priority (e.g., from `PRIORITY_UPDATE` frames). ### `stream.setPriority([options])` * `options` {Object} @@ -1950,7 +1950,7 @@ has been destroyed. ### `stream[Symbol.asyncIterator]()` * Returns: {AsyncIterableIterator} yielding {Uint8Array\[]} @@ -1983,7 +1983,7 @@ await Stream.pipeTo(stream, someWriter); ### `stream.writer` * Type: {Object} @@ -2026,7 +2026,7 @@ themselves before passing the buffer. ### `stream.setBody(body)` * `body` {string | ArrayBuffer | SharedArrayBuffer | ArrayBufferView | @@ -2220,7 +2220,7 @@ need to specify. #### `endpointOptions.disableStatelessReset` * Type: {boolean} @@ -2234,7 +2234,7 @@ at a different layer. #### `endpointOptions.idleTimeout` * Type: {number} @@ -2420,7 +2420,7 @@ Default: `'h3'` #### `sessionOptions.application` * Type: {Object} @@ -2520,7 +2520,7 @@ per-identity in the [`sessionOptions.sni`][] map. #### `sessionOptions.enableEarlyData` * Type: {boolean} **Default:** `true` @@ -2646,7 +2646,7 @@ added: v23.8.0 #### `sessionOptions.datagramDropPolicy` * Type: {string} @@ -2675,7 +2675,7 @@ reached, the datagram is dropped and reported as `'abandoned'` via the #### `sessionOptions.drainingPeriodMultiplier` * Type: {number} @@ -2701,7 +2701,7 @@ to complete before timing out. #### `sessionOptions.keepAlive` * Type: {bigint|number} @@ -2783,7 +2783,7 @@ True to enable TLS tracing output. #### `sessionOptions.token` (client only) * Type: {ArrayBufferView} @@ -2816,7 +2816,7 @@ Specifies the maximum number of unacknowledged packets a session should allow. #### `sessionOptions.rejectUnauthorized` * Type: {boolean} **Default:** `true` @@ -2830,7 +2830,7 @@ ignored. #### `sessionOptions.reuseEndpoint` * Type: {boolean} @@ -3137,7 +3137,7 @@ added: v23.8.0 ### Callback: `OnNewTokenCallback` * `this` {quic.QuicSession} @@ -3147,7 +3147,7 @@ added: REPLACEME ### Callback: `OnOriginCallback` * `this` {quic.QuicSession} @@ -3156,7 +3156,7 @@ added: REPLACEME ### Callback: `OnKeylogCallback` * `this` {quic.QuicSession} @@ -3171,7 +3171,7 @@ the secret value. ### Callback: `OnQlogCallback` * `this` {quic.QuicSession} @@ -3204,7 +3204,7 @@ added: v23.8.0 ### Callback: `OnHeadersCallback` * `this` {quic.QuicStream} @@ -3218,7 +3218,7 @@ on the client. ### Callback: `OnTrailersCallback` * `this` {quic.QuicStream} @@ -3229,7 +3229,7 @@ Called when trailing headers are received from the peer. ### Callback: `OnInfoCallback` * `this` {quic.QuicStream} @@ -3241,7 +3241,7 @@ Called when informational (1xx) headers are received from the server ## HTTP/3 support When the negotiated ALPN identifier is `'h3'` (or one of the `'h3-*'` @@ -3396,7 +3396,7 @@ Server-side notes: ## Performance measurement QUIC sessions, streams, and endpoints emit [`PerformanceEntry`][] objects @@ -3486,7 +3486,7 @@ Published when an endpoint begins listening for incoming connections. ### Channel: `quic.endpoint.connect` * `endpoint` {quic.QuicEndpoint} @@ -3639,7 +3639,7 @@ of the final statistics at the time of destruction. ### Channel: `quic.session.error` * `session` {quic.QuicSession} @@ -3694,7 +3694,7 @@ Published when a path validation attempt completes. ### Channel: `quic.session.new.token` * `token` {Buffer} The NEW\_TOKEN token data. @@ -3732,7 +3732,7 @@ server. The session is always destroyed immediately after. ### Channel: `quic.session.receive.origin` * `origins` {string\[]} The list of origins the server is authoritative for. @@ -3762,7 +3762,7 @@ Published when the TLS handshake completes. ### Channel: `quic.session.goaway` * `session` {quic.QuicSession} @@ -3776,7 +3776,7 @@ a stream boundary. ### Channel: `quic.session.early.rejected` * `session` {quic.QuicSession} @@ -3788,7 +3788,7 @@ latency regressions when 0-RTT is expected to succeed. ### Channel: `quic.stream.closed` * `stream` {quic.QuicStream} @@ -3802,7 +3802,7 @@ of the final statistics at the time of destruction. ### Channel: `quic.stream.headers` * `stream` {quic.QuicStream} @@ -3817,7 +3817,7 @@ server-side streams, this contains request pseudo-headers (`:method`, ### Channel: `quic.stream.trailers` * `stream` {quic.QuicStream} @@ -3829,7 +3829,7 @@ Published when trailing headers are received on a stream. ### Channel: `quic.stream.info` * `stream` {quic.QuicStream} @@ -3842,7 +3842,7 @@ Published when informational (1xx) headers are received on a stream ### Channel: `quic.stream.reset` * `stream` {quic.QuicStream} @@ -3857,7 +3857,7 @@ requests. ### Channel: `quic.stream.blocked` * `stream` {quic.QuicStream} diff --git a/doc/api/stream.md b/doc/api/stream.md index 95c1ab1e2dc8f5..9e34d78937d88c 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -3013,7 +3013,7 @@ const server = http.createServer((req, res) => { > Stability: 1.0 - Early development @@ -1646,7 +1646,7 @@ added: - v18.9.0 - v16.19.0 changes: - - version: REPLACEME + - version: v26.2.0 pr-url: https://github.com/nodejs/node/pull/63221 description: Added the `testTagFilters` option. - version: @@ -1884,7 +1884,7 @@ added: - v18.0.0 - v16.17.0 changes: - - version: REPLACEME + - version: v26.2.0 pr-url: https://github.com/nodejs/node/pull/63221 description: Added the `tags` option. - version: @@ -4234,7 +4234,7 @@ the second attempt is `1`, and so on. This property is useful in conjunction wit ### `context.tags` > Stability: 1.0 - Early development @@ -4462,7 +4462,7 @@ added: - v18.0.0 - v16.17.0 changes: - - version: REPLACEME + - version: v26.2.0 pr-url: https://github.com/nodejs/node/pull/63221 description: Added the `tags` option. - version: diff --git a/doc/changelogs/CHANGELOG_V26.md b/doc/changelogs/CHANGELOG_V26.md index 0576adcb2a3966..56812f4d072e2d 100644 --- a/doc/changelogs/CHANGELOG_V26.md +++ b/doc/changelogs/CHANGELOG_V26.md @@ -8,6 +8,7 @@ +26.2.0
26.1.0
26.0.0
@@ -42,6 +43,133 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + + +## 2026-05-20, Version 26.2.0 (Current), @aduh95 + +### Notable Changes + +* \[[`189d43a193`](https://github.com/nodejs/node/commit/189d43a193)] - **doc**: mark `stream.compose` stable (Matteo Collina) [#62562](https://github.com/nodejs/node/pull/62562) +* \[[`f858c6140e`](https://github.com/nodejs/node/commit/f858c6140e)] - **(SEMVER-MINOR)** **fs**: add `Temporal.Instant` support to `Stats` and `BigIntStats` (Livia Medeiros) [#60789](https://github.com/nodejs/node/pull/60789) +* \[[`0cbb3895df`](https://github.com/nodejs/node/commit/0cbb3895df)] - **(SEMVER-MINOR)** **http**: add `writeInformation` to send arbitrary 1xx status codes (Tim Perry) [#63155](https://github.com/nodejs/node/pull/63155) + +### Commits + +* \[[`9a394bab84`](https://github.com/nodejs/node/commit/9a394bab84)] - **benchmark**: respect stream/iter broadcast backpressure (Trivikram Kamat) [#63314](https://github.com/nodejs/node/pull/63314) +* \[[`ad98b4620b`](https://github.com/nodejs/node/commit/ad98b4620b)] - **crypto**: align verifyOneShot accepted types (Anshika Jain) [#63280](https://github.com/nodejs/node/pull/63280) +* \[[`ba0736a847`](https://github.com/nodejs/node/commit/ba0736a847)] - **crypto**: wire ML-DSA and ML-KEM for use when using BoringSSL (Filip Skokan) [#63255](https://github.com/nodejs/node/pull/63255) +* \[[`5573a6a4a8`](https://github.com/nodejs/node/commit/5573a6a4a8)] - **crypto**: wire ChaCha20-Poly1305 in Web Cryptography when using BoringSSL (Filip Skokan) [#63255](https://github.com/nodejs/node/pull/63255) +* \[[`7dc563b8d6`](https://github.com/nodejs/node/commit/7dc563b8d6)] - **crypto**: wire AES-KW in Web Cryptography when using BoringSSL (Filip Skokan) [#63255](https://github.com/nodejs/node/pull/63255) +* \[[`b55e2b1f4d`](https://github.com/nodejs/node/commit/b55e2b1f4d)] - **crypto**: improve system certificate enumeration logic on macOS (Robo) [#62576](https://github.com/nodejs/node/pull/62576) +* \[[`fd509a755a`](https://github.com/nodejs/node/commit/fd509a755a)] - **crypto**: harden CryptoKey algorithm slots (Filip Skokan) [#63111](https://github.com/nodejs/node/pull/63111) +* \[[`8657df39e7`](https://github.com/nodejs/node/commit/8657df39e7)] - **crypto**: harden KeyObject internal slots (Filip Skokan) [#63111](https://github.com/nodejs/node/pull/63111) +* \[[`729274e046`](https://github.com/nodejs/node/commit/729274e046)] - **crypto**: reject invalid raw key imports (Filip Skokan) [#63134](https://github.com/nodejs/node/pull/63134) +* \[[`8fc9cb9c01`](https://github.com/nodejs/node/commit/8fc9cb9c01)] - **crypto**: improve accuracy of SubtleCrypto.supports (Filip Skokan) [#63104](https://github.com/nodejs/node/pull/63104) +* \[[`288065cb3f`](https://github.com/nodejs/node/commit/288065cb3f)] - **crypto**: optimize normalizeAlgorithm dispatch hot path (Filip Skokan) [#62756](https://github.com/nodejs/node/pull/62756) +* \[[`ecf3797d09`](https://github.com/nodejs/node/commit/ecf3797d09)] - **debugger**: disambiguate probe location binding (Joyee Cheung) [#63286](https://github.com/nodejs/node/pull/63286) +* \[[`bdc57135fd`](https://github.com/nodejs/node/commit/bdc57135fd)] - **debugger**: add --help to `node inspect` and improve docs (Joyee Cheung) [#63201](https://github.com/nodejs/node/pull/63201) +* \[[`2a6e6058e9`](https://github.com/nodejs/node/commit/2a6e6058e9)] - **deps**: update undici to 8.3.0 (Node.js GitHub Bot) [#63377](https://github.com/nodejs/node/pull/63377) +* \[[`327b927271`](https://github.com/nodejs/node/commit/327b927271)] - **deps**: update corepack to 0.35.0 (Node.js GitHub Bot) [#63375](https://github.com/nodejs/node/pull/63375) +* \[[`5828fadf52`](https://github.com/nodejs/node/commit/5828fadf52)] - **deps**: update sqlite to 3.53.1 (Node.js GitHub Bot) [#63217](https://github.com/nodejs/node/pull/63217) +* \[[`fe127a999b`](https://github.com/nodejs/node/commit/fe127a999b)] - **deps**: update simdjson to 4.6.4 (Node.js GitHub Bot) [#62811](https://github.com/nodejs/node/pull/62811) +* \[[`a34c4ea159`](https://github.com/nodejs/node/commit/a34c4ea159)] - **deps**: V8: cherry-pick 435a2cdf664c (Matthias Liedtke) [#63136](https://github.com/nodejs/node/pull/63136) +* \[[`ad91efcc43`](https://github.com/nodejs/node/commit/ad91efcc43)] - **deps**: cherry-pick libuv/libuv\@a43e543 (Ali Hassan) [#63222](https://github.com/nodejs/node/pull/63222) +* \[[`5ea6c3ee7e`](https://github.com/nodejs/node/commit/5ea6c3ee7e)] - **deps**: add missing static linking targets for libffi (Paolo Insogna) [#63168](https://github.com/nodejs/node/pull/63168) +* \[[`c1f6ba22b4`](https://github.com/nodejs/node/commit/c1f6ba22b4)] - **deps**: update ngtcp2 to 1.22.1 (Node.js GitHub Bot) [#62812](https://github.com/nodejs/node/pull/62812) +* \[[`7b8767ef76`](https://github.com/nodejs/node/commit/7b8767ef76)] - **doc**: remove unsupported template type from v8.md (René) [#63410](https://github.com/nodejs/node/pull/63410) +* \[[`b2ec1880b1`](https://github.com/nodejs/node/commit/b2ec1880b1)] - **doc**: fix promise nomenclature in `stream_iter.md` (Antoine du Hamel) [#63406](https://github.com/nodejs/node/pull/63406) +* \[[`cf6cbbd39d`](https://github.com/nodejs/node/commit/cf6cbbd39d)] - **doc**: fix article usage before vowel-sound acronyms (joao-oliveira-softtor) [#62696](https://github.com/nodejs/node/pull/62696) +* \[[`da05065d98`](https://github.com/nodejs/node/commit/da05065d98)] - **doc**: remove the bi-monthly contributor spotlight section (Claudio Wunder) [#62734](https://github.com/nodejs/node/pull/62734) +* \[[`c31f320fba`](https://github.com/nodejs/node/commit/c31f320fba)] - **doc**: update http2's `push` and `trailers` events with `rawHeaders` param (YuSheng Chen) [#63259](https://github.com/nodejs/node/pull/63259) +* \[[`f0d008439b`](https://github.com/nodejs/node/commit/f0d008439b)] - **doc**: add Rust toolchain manual installation instructions Windows (Mike McCready) [#63367](https://github.com/nodejs/node/pull/63367) +* \[[`68b1220fbd`](https://github.com/nodejs/node/commit/68b1220fbd)] - **doc**: remove inactive members from Triagers list (Antoine du Hamel) [#63329](https://github.com/nodejs/node/pull/63329) +* \[[`189d43a193`](https://github.com/nodejs/node/commit/189d43a193)] - **doc**: mark stream.compose stable (Matteo Collina) [#62562](https://github.com/nodejs/node/pull/62562) +* \[[`c4fb894039`](https://github.com/nodejs/node/commit/c4fb894039)] - **doc**: fix CHANGELOG (Richard Lau) [#63292](https://github.com/nodejs/node/pull/63292) +* \[[`9f319a77e4`](https://github.com/nodejs/node/commit/9f319a77e4)] - **doc**: reference correct function in Module docs (Robin Malfait) [#63247](https://github.com/nodejs/node/pull/63247) +* \[[`2c13acc88e`](https://github.com/nodejs/node/commit/2c13acc88e)] - **doc**: replace Visual Studio 2022 Evergreen version reference with 17.14 (Mike McCready) [#63211](https://github.com/nodejs/node/pull/63211) +* \[[`7e42c336c9`](https://github.com/nodejs/node/commit/7e42c336c9)] - **doc**: recommend explicitly Tier 1 or 2 for production applications (Mike McCready) [#63187](https://github.com/nodejs/node/pull/63187) +* \[[`d99e0bb6d5`](https://github.com/nodejs/node/commit/d99e0bb6d5)] - **doc**: document Temporal configure flags in BUILDING.md (ChrisJr404) [#63248](https://github.com/nodejs/node/pull/63248) +* \[[`c0ea77b305`](https://github.com/nodejs/node/commit/c0ea77b305)] - **doc**: run license-builder (github-actions\[bot]) [#63232](https://github.com/nodejs/node/pull/63232) +* \[[`8265aba0f4`](https://github.com/nodejs/node/commit/8265aba0f4)] - **doc**: add large pull requests contributing guide (Matteo Collina) [#62829](https://github.com/nodejs/node/pull/62829) +* \[[`be241bacc8`](https://github.com/nodejs/node/commit/be241bacc8)] - **doc**: remove unnecessary ` > Stability: 1.1 - Active development @@ -1355,6 +1357,7 @@ Use this flag to enable [ShadowRealm][] support. > Stability: 1.1 - Active Development @@ -2893,7 +2896,9 @@ option set. This flag is not necessary when test isolation is disabled. ### `--test-random-seed` Set the seed used to randomize test execution order. This applies to both test @@ -2907,7 +2912,9 @@ This flag cannot be used with `--watch` or `--test-rerun-failures`. ### `--test-randomize` Randomize test execution order. This applies to both test file execution order diff --git a/doc/api/crypto.md b/doc/api/crypto.md index efb3fa4a6cf0ee..00a77f38a6d3b3 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -5850,7 +5850,9 @@ cryptographic pseudorandom number generator. ### `crypto.randomUUIDv7([options])` * `options` {Object} @@ -6102,7 +6104,9 @@ Throws an error if FIPS mode is not available. > Stability: 1 - Experimental. diff --git a/doc/api/fs.md b/doc/api/fs.md index e1211e4cd25f3f..8c20afd92182de 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -780,7 +780,9 @@ Read from a file and write to an array of {ArrayBufferView}s * Type: {number|bigint} diff --git a/doc/api/http.md b/doc/api/http.md index 0775ad1a1a0dec..41ecdf6d00b3be 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -3030,7 +3030,9 @@ Calls `message.socket.setTimeout(msecs, callback)`. ### `message.signal` * Type: {AbortSignal} diff --git a/doc/api/inspector.md b/doc/api/inspector.md index 4cdbeb62d0e71a..8c6f45e3d15a88 100644 --- a/doc/api/inspector.md +++ b/doc/api/inspector.md @@ -687,6 +687,7 @@ For more details, see the official CDP documentation: [Network.loadNetworkResour * `params` {Object} @@ -708,6 +709,7 @@ This event indicates that a new item has been added to the storage. * `params` {Object} @@ -728,6 +730,7 @@ This event indicates that an item has been removed from the storage. * `params` {Object} @@ -750,6 +753,7 @@ This event indicates that a storage item has been updated. * `params` {Object} @@ -770,6 +774,7 @@ storage. * `params` {Object} diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 29c0bff1fab712..1679710cfa1b30 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -2578,7 +2578,9 @@ JavaScript `ArrayBuffer`s are described in #### `node_api_create_external_sharedarraybuffer` ```c diff --git a/doc/api/quic.md b/doc/api/quic.md index 4ad25810ab4627..7e765f21083bea 100644 --- a/doc/api/quic.md +++ b/doc/api/quic.md @@ -577,7 +577,9 @@ The valid range is `0` to `65535`. ### `endpoint.setSNIContexts(entries[, options])` * `entries` {object} An object mapping host names to TLS identity options. @@ -2396,7 +2398,9 @@ added: v23.8.0 #### `sessionOptions.alpn` * Type: {string} (client) | {string\[]} (server) @@ -2725,7 +2729,9 @@ The peer server name to target (SNI). Defaults to `'localhost'`. #### `sessionOptions.sni` (server only) * Type: {Object} diff --git a/doc/api/sqlite.md b/doc/api/sqlite.md index f4eb4e9c862961..e277457c00dea7 100644 --- a/doc/api/sqlite.md +++ b/doc/api/sqlite.md @@ -562,7 +562,9 @@ the constructor. An exception is thrown if the database is already open. ### `database.serialize([dbName])` * `dbName` {string} Name of the database to serialize. This can be `'main'` @@ -597,7 +599,9 @@ console.log(buffer.length); // Prints the byte length of the database ### `database.deserialize(buffer[, options])` * `buffer` {Uint8Array} A binary representation of a database, such as the diff --git a/doc/api/test.md b/doc/api/test.md index 830c5434a49544..19b7e87e099221 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -706,7 +706,9 @@ node --test "**/*.test.js" "**/*.spec.js" ### Randomizing tests execution order > Stability: 1.0 - Early development @@ -3833,7 +3835,9 @@ with. ## Test instrumentation and OpenTelemetry The test runner publishes test execution events through the Node.js @@ -4610,7 +4614,9 @@ Can be used to abort test subtasks when the test has been aborted. ### `context.passed` * Type: {boolean} @@ -4620,7 +4626,9 @@ Indicates whether the suite and all of its subtests have passed. ### `context.attempt` * Type: {number} @@ -4632,7 +4640,9 @@ the second attempt is `1`, and so on. This property is useful in conjunction wit ### `context.diagnostic(message)` * `message` {string} A diagnostic message to output. diff --git a/doc/api/util.md b/doc/api/util.md index 770322b29d5e07..568d575c3d8735 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -2548,7 +2548,9 @@ added: - v21.7.0 - v20.12.0 changes: - - version: v26.1.0 + - version: + - v26.1.0 + - v24.16.0 pr-url: https://github.com/nodejs/node/pull/61556 description: Add support for hexadecimal colors. - version: diff --git a/doc/changelogs/CHANGELOG_V24.md b/doc/changelogs/CHANGELOG_V24.md index f0e903b3349c0a..6ba0beb61bcdcc 100644 --- a/doc/changelogs/CHANGELOG_V24.md +++ b/doc/changelogs/CHANGELOG_V24.md @@ -9,6 +9,7 @@ +24.16.0
24.15.0
24.14.1
24.14.0
@@ -65,6 +66,256 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + + +## 2026-05-21, Version 24.16.0 'Krypton' (LTS), @aduh95 + +### Notable Changes + +* \[[`b267f6bca3`](https://github.com/nodejs/node/commit/b267f6bca3)] - **(SEMVER-MINOR)** **crypto**: implement `randomUUIDv7()` (nabeel378) [#62553](https://github.com/nodejs/node/pull/62553) +* \[[`ec2451b9cd`](https://github.com/nodejs/node/commit/ec2451b9cd)] - **(SEMVER-MINOR)** **debugger**: add edit-free runtime expression probes to `node inspect` (Joyee Cheung) [#62713](https://github.com/nodejs/node/pull/62713) +* \[[`9705f628d9`](https://github.com/nodejs/node/commit/9705f628d9)] - **(SEMVER-MINOR)** **fs**: add signal option to `fs.stat()` (Mert Can Altin) [#57775](https://github.com/nodejs/node/pull/57775) +* \[[`40ccfdecf9`](https://github.com/nodejs/node/commit/40ccfdecf9)] - **(SEMVER-MINOR)** **fs**: expose `frsize` field in `statfs` (Jinho Jang) [#62277](https://github.com/nodejs/node/pull/62277) +* \[[`d7188af5c9`](https://github.com/nodejs/node/commit/d7188af5c9)] - **(SEMVER-MINOR)** **http**: harden `ClientRequest` options merge (Matteo Collina) [#63082](https://github.com/nodejs/node/pull/63082) +* \[[`aa1d8a9afc`](https://github.com/nodejs/node/commit/aa1d8a9afc)] - **(SEMVER-MINOR)** **http**: add `req.signal` to `IncomingMessage` (Akshat) [#62541](https://github.com/nodejs/node/pull/62541) +* \[[`6f37f7e240`](https://github.com/nodejs/node/commit/6f37f7e240)] - **(SEMVER-MINOR)** **stream**: propagate destruction in `duplexPair` (Ahmed Elhor) [#61098](https://github.com/nodejs/node/pull/61098) +* \[[`d14029be7f`](https://github.com/nodejs/node/commit/d14029be7f)] - **(SEMVER-MINOR)** **test\_runner**: support test order randomization (Pietro Marchini) [#61747](https://github.com/nodejs/node/pull/61747) +* \[[`d142c584cd`](https://github.com/nodejs/node/commit/d142c584cd)] - **(SEMVER-MINOR)** **test\_runner**: align mock timeout api (sangwook) [#62820](https://github.com/nodejs/node/pull/62820) +* \[[`01a9552585`](https://github.com/nodejs/node/commit/01a9552585)] - **(SEMVER-MINOR)** **test\_runner**: add mock-timers support for `AbortSignal.timeout` (DeveloperViraj) [#60751](https://github.com/nodejs/node/pull/60751) +* \[[`00705a459a`](https://github.com/nodejs/node/commit/00705a459a)] - **(SEMVER-MINOR)** **util**: colorize text with hex colors (Guilherme Araújo) [#61556](https://github.com/nodejs/node/pull/61556) + +### Commits + +* \[[`dd72df060d`](https://github.com/nodejs/node/commit/dd72df060d)] - **assert,util**: fix stale nested cycle memo entries (Ruben Bridgewater) [#62509](https://github.com/nodejs/node/pull/62509) +* \[[`add94f4bc3`](https://github.com/nodejs/node/commit/add94f4bc3)] - **build**: track PDL files as inputs in inspector GN build (Robo) [#62888](https://github.com/nodejs/node/pull/62888) +* \[[`1b1eb9e334`](https://github.com/nodejs/node/commit/1b1eb9e334)] - **build**: remove redundant -fuse-linker-plugin from GCC LTO flags (Daniel Lando) [#62667](https://github.com/nodejs/node/pull/62667) +* \[[`8752b604ec`](https://github.com/nodejs/node/commit/8752b604ec)] - **crypto**: deduplicate and canonicalize CryptoKey usages (Filip Skokan) [#62902](https://github.com/nodejs/node/pull/62902) +* \[[`341947e7fd`](https://github.com/nodejs/node/commit/341947e7fd)] - **crypto**: reject unintended raw key format string input (Filip Skokan) [#62974](https://github.com/nodejs/node/pull/62974) +* \[[`28a78747fc`](https://github.com/nodejs/node/commit/28a78747fc)] - **crypto**: remove Argon2 KDF derivation from its job setup (Filip Skokan) [#62863](https://github.com/nodejs/node/pull/62863) +* \[[`16e8c2b54d`](https://github.com/nodejs/node/commit/16e8c2b54d)] - **crypto**: fix unsigned conversion of 4-byte RSA publicExponent (DeepView Autofix) [#62839](https://github.com/nodejs/node/pull/62839) +* \[[`eeae754a87`](https://github.com/nodejs/node/commit/eeae754a87)] - **crypto**: reject inherited key type names (Jonathan Lopes) [#62875](https://github.com/nodejs/node/pull/62875) +* \[[`9dd5540325`](https://github.com/nodejs/node/commit/9dd5540325)] - **crypto**: add memory tracking for secureContext openssl objects (Mert Can Altin) [#59051](https://github.com/nodejs/node/pull/59051) +* \[[`b267f6bca3`](https://github.com/nodejs/node/commit/b267f6bca3)] - **(SEMVER-MINOR)** **crypto**: implement randomUUIDv7() (nabeel378) [#62553](https://github.com/nodejs/node/pull/62553) +* \[[`7597d204c1`](https://github.com/nodejs/node/commit/7597d204c1)] - **crypto**: add support for Ed25519 context parameter (Filip Skokan) [#62474](https://github.com/nodejs/node/pull/62474) +* \[[`4bf85845da`](https://github.com/nodejs/node/commit/4bf85845da)] - **debugger**: move ProbeInspectorSession and helpers to separate files (Joyee Cheung) [#63013](https://github.com/nodejs/node/pull/63013) +* \[[`ec2451b9cd`](https://github.com/nodejs/node/commit/ec2451b9cd)] - **(SEMVER-MINOR)** **debugger**: add edit-free runtime expression probes to `node inspect` (Joyee Cheung) [#62713](https://github.com/nodejs/node/pull/62713) +* \[[`83e98f77b7`](https://github.com/nodejs/node/commit/83e98f77b7)] - **deps**: update corepack to 0.35.0 (Node.js GitHub Bot) [#63375](https://github.com/nodejs/node/pull/63375) +* \[[`ec8c6b939a`](https://github.com/nodejs/node/commit/ec8c6b939a)] - **deps**: V8: cherry-pick 657d8de27427 (Guy Bedford) [#62784](https://github.com/nodejs/node/pull/62784) +* \[[`722c0c3274`](https://github.com/nodejs/node/commit/722c0c3274)] - **deps**: update nghttp3 to 1.14.0 (Node.js GitHub Bot) [#61187](https://github.com/nodejs/node/pull/61187) +* \[[`5304db93d3`](https://github.com/nodejs/node/commit/5304db93d3)] - **deps**: update nghttp3 to 1.13.1 (Node.js GitHub Bot) [#60046](https://github.com/nodejs/node/pull/60046) +* \[[`e073b3811d`](https://github.com/nodejs/node/commit/e073b3811d)] - **deps**: update nghttp3 to 1.11.0 (James M Snell) [#59249](https://github.com/nodejs/node/pull/59249) +* \[[`1d00313fb2`](https://github.com/nodejs/node/commit/1d00313fb2)] - **deps**: update ngtcp2 to 1.14.0 (James M Snell) [#59249](https://github.com/nodejs/node/pull/59249) +* \[[`8b3a4fc18f`](https://github.com/nodejs/node/commit/8b3a4fc18f)] - **deps**: update amaro to 1.1.9 (Node.js GitHub Bot) [#63090](https://github.com/nodejs/node/pull/63090) +* \[[`62fe0cfcd1`](https://github.com/nodejs/node/commit/62fe0cfcd1)] - **deps**: update llhttp to 9.4.1 (Node.js GitHub Bot) [#63045](https://github.com/nodejs/node/pull/63045) +* \[[`137e09c8e9`](https://github.com/nodejs/node/commit/137e09c8e9)] - **deps**: update corepack to 0.34.7 (Node.js GitHub Bot) [#62810](https://github.com/nodejs/node/pull/62810) +* \[[`14a4cb8fbc`](https://github.com/nodejs/node/commit/14a4cb8fbc)] - **deps**: update timezone to 2026b (Node.js GitHub Bot) [#62962](https://github.com/nodejs/node/pull/62962) +* \[[`3e1036583a`](https://github.com/nodejs/node/commit/3e1036583a)] - **deps**: upgrade npm to 11.13.0 (npm team) [#62898](https://github.com/nodejs/node/pull/62898) +* \[[`01dfe5961c`](https://github.com/nodejs/node/commit/01dfe5961c)] - **deps**: cherry-pick libuv/libuv\@439a54b (skooch) [#62881](https://github.com/nodejs/node/pull/62881) +* \[[`6cd368b10c`](https://github.com/nodejs/node/commit/6cd368b10c)] - **deps**: update sqlite to 3.53.0 (Node.js GitHub Bot) [#62699](https://github.com/nodejs/node/pull/62699) +* \[[`f218a4f553`](https://github.com/nodejs/node/commit/f218a4f553)] - **deps**: update nbytes to 0.1.4 (Node.js GitHub Bot) [#62698](https://github.com/nodejs/node/pull/62698) +* \[[`b47688524a`](https://github.com/nodejs/node/commit/b47688524a)] - **deps**: update archs files for openssl-3.5.6 (Node.js GitHub Bot) [#62629](https://github.com/nodejs/node/pull/62629) +* \[[`d202e2d343`](https://github.com/nodejs/node/commit/d202e2d343)] - **deps**: upgrade openssl sources to openssl-3.5.6 (Node.js GitHub Bot) [#62629](https://github.com/nodejs/node/pull/62629) +* \[[`2faba66341`](https://github.com/nodejs/node/commit/2faba66341)] - **deps**: update minimatch to 10.2.5 (Node.js GitHub Bot) [#62594](https://github.com/nodejs/node/pull/62594) +* \[[`fa46c90c5d`](https://github.com/nodejs/node/commit/fa46c90c5d)] - **deps**: update googletest to d72f9c8aea6817cdf1ca0ac10887f328de7f3da2 (Node.js GitHub Bot) [#62593](https://github.com/nodejs/node/pull/62593) +* \[[`099ded5713`](https://github.com/nodejs/node/commit/099ded5713)] - **deps**: update simdjson to 4.6.1 (Node.js GitHub Bot) [#62592](https://github.com/nodejs/node/pull/62592) +* \[[`7ce95afe96`](https://github.com/nodejs/node/commit/7ce95afe96)] - **deps**: libuv: cherry-pick aabb7651de (Santiago Gimeno) [#62561](https://github.com/nodejs/node/pull/62561) +* \[[`57ef845623`](https://github.com/nodejs/node/commit/57ef845623)] - **deps**: update icu to 78.3 (Node.js GitHub Bot) [#62324](https://github.com/nodejs/node/pull/62324) +* \[[`493ac40e12`](https://github.com/nodejs/node/commit/493ac40e12)] - **deps**: update libuv to 1.52.1 (Node.js GitHub Bot) [#61829](https://github.com/nodejs/node/pull/61829) +* \[[`b39508b368`](https://github.com/nodejs/node/commit/b39508b368)] - **deps**: update undici to 7.25.0 (Node.js GitHub Bot) [#63011](https://github.com/nodejs/node/pull/63011) +* \[[`cb67a925e9`](https://github.com/nodejs/node/commit/cb67a925e9)] - **deps**: use npm undici\@seven tag in `update-undici.sh` (Matteo Collina) [#62739](https://github.com/nodejs/node/pull/62739) +* \[[`aa1e0bc28b`](https://github.com/nodejs/node/commit/aa1e0bc28b)] - **doc**: fix typos and inconsistencies in crypto.md and webcrypto.md (Filip Skokan) [#62828](https://github.com/nodejs/node/pull/62828) +* \[[`f2a1735ed9`](https://github.com/nodejs/node/commit/f2a1735ed9)] - **doc**: fix duplicate word "to to" in util.styleText (Daijiro Wachi) [#62917](https://github.com/nodejs/node/pull/62917) +* \[[`b6378e215c`](https://github.com/nodejs/node/commit/b6378e215c)] - **doc**: fix node-config-schema (Сковорода Никита Андреевич) [#61596](https://github.com/nodejs/node/pull/61596) +* \[[`233894a9ce`](https://github.com/nodejs/node/commit/233894a9ce)] - **doc**: fix the TypeScript Execute (tsx) project link (David Thornton) [#63093](https://github.com/nodejs/node/pull/63093) +* \[[`5d97919f8f`](https://github.com/nodejs/node/commit/5d97919f8f)] - **doc**: correct diagnostics\_channel built-in channel names (Bryan English) [#62995](https://github.com/nodejs/node/pull/62995) +* \[[`2a9ccc927e`](https://github.com/nodejs/node/commit/2a9ccc927e)] - **doc**: use mjs/cjs blocks for callbackify null reason example (Daijiro Wachi) [#62884](https://github.com/nodejs/node/pull/62884) +* \[[`ef413b5358`](https://github.com/nodejs/node/commit/ef413b5358)] - **doc**: fix typo in test.md (Rich Trott) [#62960](https://github.com/nodejs/node/pull/62960) +* \[[`76f21c5070`](https://github.com/nodejs/node/commit/76f21c5070)] - **doc**: correct typo in PR contribution instructions (Mike McCready) [#62738](https://github.com/nodejs/node/pull/62738) +* \[[`ca02af1f7d`](https://github.com/nodejs/node/commit/ca02af1f7d)] - **doc**: fix duplicate word "of of" in postMessageToThread (Daijiro Wachi) [#62917](https://github.com/nodejs/node/pull/62917) +* \[[`46c99ed526`](https://github.com/nodejs/node/commit/46c99ed526)] - **doc**: fix duplicate word "for for" in compile cache (Daijiro Wachi) [#62917](https://github.com/nodejs/node/pull/62917) +* \[[`1a60851734`](https://github.com/nodejs/node/commit/1a60851734)] - **doc**: fix typo in dns.lookup options description (Daijiro Wachi) [#62882](https://github.com/nodejs/node/pull/62882) +* \[[`169b5ea2ed`](https://github.com/nodejs/node/commit/169b5ea2ed)] - **doc**: fix Argon2 parameter bounds (Tobias Nießen) [#62868](https://github.com/nodejs/node/pull/62868) +* \[[`9a3a190f4e`](https://github.com/nodejs/node/commit/9a3a190f4e)] - **doc**: clarify diffieHellman.generateKeys recomputes same key (Kit Dallege) [#62205](https://github.com/nodejs/node/pull/62205) +* \[[`0fba9e87d6`](https://github.com/nodejs/node/commit/0fba9e87d6)] - **doc**: remove Ayase-252 and meixg from triagger team (Antoine du Hamel) [#62841](https://github.com/nodejs/node/pull/62841) +* \[[`9c700f3446`](https://github.com/nodejs/node/commit/9c700f3446)] - **doc**: clarify dns.lookup() callback signature when all is true (eungi) [#62800](https://github.com/nodejs/node/pull/62800) +* \[[`6b7280bc17`](https://github.com/nodejs/node/commit/6b7280bc17)] - **doc**: add experimental modules lifetime policy (Paolo Insogna) [#62753](https://github.com/nodejs/node/pull/62753) +* \[[`ce47ea31c9`](https://github.com/nodejs/node/commit/ce47ea31c9)] - **doc**: clarify process.\_debugProcess() in Permission Model (Fahad Khan) [#62537](https://github.com/nodejs/node/pull/62537) +* \[[`ba01633757`](https://github.com/nodejs/node/commit/ba01633757)] - **doc**: fix typo in devcontainer guide (Rohan Santhosh Kumar) [#62687](https://github.com/nodejs/node/pull/62687) +* \[[`70b4d5839b`](https://github.com/nodejs/node/commit/70b4d5839b)] - **doc**: clarify Backport-PR-URL metadata added automatically (Mike McCready) [#62668](https://github.com/nodejs/node/pull/62668) +* \[[`8126d1c3eb`](https://github.com/nodejs/node/commit/8126d1c3eb)] - **doc**: update WPT test runner README.md (Filip Skokan) [#62680](https://github.com/nodejs/node/pull/62680) +* \[[`978afea4b5`](https://github.com/nodejs/node/commit/978afea4b5)] - **doc**: fix spelling in release announcement guidance (Rohan Santhosh Kumar) [#62663](https://github.com/nodejs/node/pull/62663) +* \[[`1684ab8ff8`](https://github.com/nodejs/node/commit/1684ab8ff8)] - **doc**: note non-monotonic clock in crypto.randomUUIDv7 (nabeel378) [#62600](https://github.com/nodejs/node/pull/62600) +* \[[`86d4f07930`](https://github.com/nodejs/node/commit/86d4f07930)] - **doc**: update bug bounty program (Rafael Gonzaga) [#62590](https://github.com/nodejs/node/pull/62590) +* \[[`736ed8a08f`](https://github.com/nodejs/node/commit/736ed8a08f)] - **doc**: document TransformStream transformer.cancel option (Tom Pereira) [#62566](https://github.com/nodejs/node/pull/62566) +* \[[`938af9be01`](https://github.com/nodejs/node/commit/938af9be01)] - **doc**: mention test runner retry attemp is zero based (Moshe Atlow) [#62504](https://github.com/nodejs/node/pull/62504) +* \[[`94433e450f`](https://github.com/nodejs/node/commit/94433e450f)] - **doc,src,test**: fix dead inspector help URL (semimikoh) [#62745](https://github.com/nodejs/node/pull/62745) +* \[[`ddf1f01659`](https://github.com/nodejs/node/commit/ddf1f01659)] - **esm**: add `ERR_REQUIRE_ESM_RACE_CONDITION` (Antoine du Hamel) [#62462](https://github.com/nodejs/node/pull/62462) +* \[[`4a506acd16`](https://github.com/nodejs/node/commit/4a506acd16)] - **fs**: add followSymlinks option to glob (Matteo Collina) [#62695](https://github.com/nodejs/node/pull/62695) +* \[[`f4ea495f9b`](https://github.com/nodejs/node/commit/f4ea495f9b)] - **fs**: restore fs patchability in ESM loader (Joyee Cheung) [#62835](https://github.com/nodejs/node/pull/62835) +* \[[`63c111cd60`](https://github.com/nodejs/node/commit/63c111cd60)] - **fs**: validate position argument before length === 0 early return (Edy Silva) [#62674](https://github.com/nodejs/node/pull/62674) +* \[[`9705f628d9`](https://github.com/nodejs/node/commit/9705f628d9)] - **(SEMVER-MINOR)** **fs**: add signal option to fs.stat() (Mert Can Altin) [#57775](https://github.com/nodejs/node/pull/57775) +* \[[`40ccfdecf9`](https://github.com/nodejs/node/commit/40ccfdecf9)] - **(SEMVER-MINOR)** **fs**: expose frsize field in statfs (Jinho Jang) [#62277](https://github.com/nodejs/node/pull/62277) +* \[[`717476a24e`](https://github.com/nodejs/node/commit/717476a24e)] - **http**: emit 'drain' on OutgoingMessage only after buffers drain (Robert Nagy) [#62936](https://github.com/nodejs/node/pull/62936) +* \[[`d7188af5c9`](https://github.com/nodejs/node/commit/d7188af5c9)] - **(SEMVER-MINOR)** **http**: harden ClientRequest options merge (Matteo Collina) [#63082](https://github.com/nodejs/node/pull/63082) +* \[[`64f15c274a`](https://github.com/nodejs/node/commit/64f15c274a)] - **http**: fix leaked error listener on sync HTTP req create + destroy (Tim Perry) [#62872](https://github.com/nodejs/node/pull/62872) +* \[[`5c4798d799`](https://github.com/nodejs/node/commit/5c4798d799)] - **http**: fix no\_proxy leading-dot suffix matching (Daijiro Wachi) [#62333](https://github.com/nodejs/node/pull/62333) +* \[[`9f3bc70ae5`](https://github.com/nodejs/node/commit/9f3bc70ae5)] - **http**: cleanup pipeline queue (Robert Nagy) [#62534](https://github.com/nodejs/node/pull/62534) +* \[[`aa1d8a9afc`](https://github.com/nodejs/node/commit/aa1d8a9afc)] - **(SEMVER-MINOR)** **http**: add req.signal to IncomingMessage (Akshat) [#62541](https://github.com/nodejs/node/pull/62541) +* \[[`900dc758ff`](https://github.com/nodejs/node/commit/900dc758ff)] - **http2**: expose writable stream state on compat response (T) [#63003](https://github.com/nodejs/node/pull/63003) +* \[[`b3bfe35912`](https://github.com/nodejs/node/commit/b3bfe35912)] - **inspector**: coerce key and value to string in webstorage events (Ali Hassan) [#62616](https://github.com/nodejs/node/pull/62616) +* \[[`3dc3fb6ad8`](https://github.com/nodejs/node/commit/3dc3fb6ad8)] - **inspector**: return errors when CDP protocol event emission fails (Ryuhei Shima) [#62162](https://github.com/nodejs/node/pull/62162) +* \[[`4f3f21bd7c`](https://github.com/nodejs/node/commit/4f3f21bd7c)] - **inspector**: auto collect webstorage data (Ryuhei Shima) [#62145](https://github.com/nodejs/node/pull/62145) +* \[[`36cc04189d`](https://github.com/nodejs/node/commit/36cc04189d)] - **inspector**: initial support storage inspection (Ryuhei Shima) [#61139](https://github.com/nodejs/node/pull/61139) +* \[[`1718bc3b9b`](https://github.com/nodejs/node/commit/1718bc3b9b)] - **inspector**: fix absolute URLs in network http (bugyaluwang) [#62955](https://github.com/nodejs/node/pull/62955) +* \[[`97e32c7a74`](https://github.com/nodejs/node/commit/97e32c7a74)] - **lib**: avoid quadratic shift() in startup snapshot callback (Daijiro Wachi) [#62914](https://github.com/nodejs/node/pull/62914) +* \[[`25d2e999de`](https://github.com/nodejs/node/commit/25d2e999de)] - **lib**: harden kKeyOps lookup with null prototype (Filip Skokan) [#62877](https://github.com/nodejs/node/pull/62877) +* \[[`37d3913c8f`](https://github.com/nodejs/node/commit/37d3913c8f)] - **lib**: short-circuit WebIDL BufferSource SAB check (Filip Skokan) [#62833](https://github.com/nodejs/node/pull/62833) +* \[[`430c69d25f`](https://github.com/nodejs/node/commit/430c69d25f)] - **lib**: use js-only implementation of `isDataView()` (René) [#62780](https://github.com/nodejs/node/pull/62780) +* \[[`3ba0add6a0`](https://github.com/nodejs/node/commit/3ba0add6a0)] - **lib**: fix lint in internal/webstreams/util.js (Filip Skokan) [#62806](https://github.com/nodejs/node/pull/62806) +* \[[`9b95c41398`](https://github.com/nodejs/node/commit/9b95c41398)] - **lib**: fix sequence argument handling in Blob constructor (Ms2ger) [#62179](https://github.com/nodejs/node/pull/62179) +* \[[`314dacdbee`](https://github.com/nodejs/node/commit/314dacdbee)] - **lib**: improve Web Cryptography key validation ordering (Filip Skokan) [#62749](https://github.com/nodejs/node/pull/62749) +* \[[`3d18162430`](https://github.com/nodejs/node/commit/3d18162430)] - **lib**: reject SharedArrayBuffer in web APIs per spec (Ali Hassan) [#62632](https://github.com/nodejs/node/pull/62632) +* \[[`ada3ce879d`](https://github.com/nodejs/node/commit/ada3ce879d)] - **lib**: defer AbortSignal.any() following (sangwook) [#62367](https://github.com/nodejs/node/pull/62367) +* \[[`b2981ec7eb`](https://github.com/nodejs/node/commit/b2981ec7eb)] - **meta**: bump actions/download-artifact from 8.0.0 to 8.0.1 (dependabot\[bot]) [#62549](https://github.com/nodejs/node/pull/62549) +* \[[`7cd20667b5`](https://github.com/nodejs/node/commit/7cd20667b5)] - **meta**: bump github/codeql-action from 4.35.1 to 4.35.3 (dependabot\[bot]) [#63074](https://github.com/nodejs/node/pull/63074) +* \[[`91a07cfe9f`](https://github.com/nodejs/node/commit/91a07cfe9f)] - **meta**: bump Mozilla-Actions/sccache-action from 0.0.9 to 0.0.10 (dependabot\[bot]) [#63073](https://github.com/nodejs/node/pull/63073) +* \[[`09e17fe47c`](https://github.com/nodejs/node/commit/09e17fe47c)] - **meta**: add automation policy (Chengzhong Wu) [#62871](https://github.com/nodejs/node/pull/62871) +* \[[`59e7fb7986`](https://github.com/nodejs/node/commit/59e7fb7986)] - **meta**: move VoltrexKeyva to emeritus (Matteo Collina) [#62895](https://github.com/nodejs/node/pull/62895) +* \[[`1e2915cfa6`](https://github.com/nodejs/node/commit/1e2915cfa6)] - **meta**: bump peter-evans/create-pull-request from 8.1.0 to 8.1.1 (dependabot\[bot]) [#62845](https://github.com/nodejs/node/pull/62845) +* \[[`0253c6e2be`](https://github.com/nodejs/node/commit/0253c6e2be)] - **meta**: bump step-security/harden-runner from 2.16.1 to 2.19.0 (dependabot\[bot]) [#62844](https://github.com/nodejs/node/pull/62844) +* \[[`f503675b86`](https://github.com/nodejs/node/commit/f503675b86)] - **meta**: bump actions/setup-node from 6.3.0 to 6.4.0 (dependabot\[bot]) [#62842](https://github.com/nodejs/node/pull/62842) +* \[[`5e14e4d26e`](https://github.com/nodejs/node/commit/5e14e4d26e)] - **meta**: broaden stale bot (Aviv Keller) [#62658](https://github.com/nodejs/node/pull/62658) +* \[[`795db76f87`](https://github.com/nodejs/node/commit/795db76f87)] - **meta**: pass release version to release worker (flakey5) [#62777](https://github.com/nodejs/node/pull/62777) +* \[[`ef384fe39f`](https://github.com/nodejs/node/commit/ef384fe39f)] - **meta**: add QUIC to CODEOWNERS (Tim Perry) [#62652](https://github.com/nodejs/node/pull/62652) +* \[[`67e0ac568d`](https://github.com/nodejs/node/commit/67e0ac568d)] - **meta**: move Michael to emeritus (Michael Dawson) [#62536](https://github.com/nodejs/node/pull/62536) +* \[[`5dad616393`](https://github.com/nodejs/node/commit/5dad616393)] - **meta**: populate apt list for slim runner in update-openssl workflow (René) [#62628](https://github.com/nodejs/node/pull/62628) +* \[[`a869d25d8a`](https://github.com/nodejs/node/commit/a869d25d8a)] - **meta**: bump step-security/harden-runner from 2.15.0 to 2.16.1 (dependabot\[bot]) [#62550](https://github.com/nodejs/node/pull/62550) +* \[[`769efc0403`](https://github.com/nodejs/node/commit/769efc0403)] - **meta**: bump actions/setup-node from 6.2.0 to 6.3.0 (dependabot\[bot]) [#62548](https://github.com/nodejs/node/pull/62548) +* \[[`73fcc2b055`](https://github.com/nodejs/node/commit/73fcc2b055)] - **meta**: bump github/codeql-action from 4.32.4 to 4.35.1 (dependabot\[bot]) [#62547](https://github.com/nodejs/node/pull/62547) +* \[[`6c001246fe`](https://github.com/nodejs/node/commit/6c001246fe)] - **meta**: bump codecov/codecov-action from 5.5.2 to 6.0.0 (dependabot\[bot]) [#62545](https://github.com/nodejs/node/pull/62545) +* \[[`5ee40d6a03`](https://github.com/nodejs/node/commit/5ee40d6a03)] - **meta**: bump actions/cache from 5.0.3 to 5.0.4 (dependabot\[bot]) [#62543](https://github.com/nodejs/node/pull/62543) +* \[[`ca16ad8a05`](https://github.com/nodejs/node/commit/ca16ad8a05)] - **meta**: require DCO signoff in commit message guidelines (James M Snell) [#62510](https://github.com/nodejs/node/pull/62510) +* \[[`db9497fc41`](https://github.com/nodejs/node/commit/db9497fc41)] - **meta**: expand memory leak DoS criteria to all DoS (Joyee Cheung) [#62505](https://github.com/nodejs/node/pull/62505) +* \[[`13b7d08b8d`](https://github.com/nodejs/node/commit/13b7d08b8d)] - **module**: remove duplicated checks from `_resolveFilename` (Antoine du Hamel) [#62729](https://github.com/nodejs/node/pull/62729) +* \[[`6b53efb53a`](https://github.com/nodejs/node/commit/6b53efb53a)] - **module,win**: fix long subpath import (Stefan Stojanovic) [#62101](https://github.com/nodejs/node/pull/62101) +* \[[`841dfbf6fc`](https://github.com/nodejs/node/commit/841dfbf6fc)] - **node-api**: update libuv ABI stability note (Chengzhong Wu) [#62789](https://github.com/nodejs/node/pull/62789) +* \[[`01090f2aa1`](https://github.com/nodejs/node/commit/01090f2aa1)] - **node-api**: add napi\_create\_external\_sharedarraybuffer (Ben Noordhuis) [#62623](https://github.com/nodejs/node/pull/62623) +* \[[`87443b4355`](https://github.com/nodejs/node/commit/87443b4355)] - **node-api**: execute tsfn finalizer after queue drains when aborted (Kevin Eady) [#61956](https://github.com/nodejs/node/pull/61956) +* \[[`e95570c054`](https://github.com/nodejs/node/commit/e95570c054)] - **process**: handle rejections only when needed (Gürgün Dayıoğlu) [#62919](https://github.com/nodejs/node/pull/62919) +* \[[`37d49f3219`](https://github.com/nodejs/node/commit/37d49f3219)] - **process**: optimize asyncHandledRejections by using FixedQueue (Gürgün Dayıoğlu) [#60854](https://github.com/nodejs/node/pull/60854) +* \[[`f697c55e38`](https://github.com/nodejs/node/commit/f697c55e38)] - **quic**: add QuicEndpoint.listening & QuicStream.destroy() and tests (Tim Perry) [#62648](https://github.com/nodejs/node/pull/62648) +* \[[`c128942b69`](https://github.com/nodejs/node/commit/c128942b69)] - **quic**: fixup token verification to handle zero expiration (James M Snell) [#62620](https://github.com/nodejs/node/pull/62620) +* \[[`abb881ec92`](https://github.com/nodejs/node/commit/abb881ec92)] - **quic**: support multiple ALPN negotiation (James M Snell) [#62620](https://github.com/nodejs/node/pull/62620) +* \[[`476926c2ad`](https://github.com/nodejs/node/commit/476926c2ad)] - **quic**: apply multiple TLS context improvements and SNI support (James M Snell) [#62620](https://github.com/nodejs/node/pull/62620) +* \[[`76d9c24b95`](https://github.com/nodejs/node/commit/76d9c24b95)] - **quic**: implement rapidhash for hashing improvements (James M Snell) [#62620](https://github.com/nodejs/node/pull/62620) +* \[[`08726cd43d`](https://github.com/nodejs/node/commit/08726cd43d)] - **quic**: move quic behind compile time flag (Matteo Collina) [#61444](https://github.com/nodejs/node/pull/61444) +* \[[`ea4f19aaa7`](https://github.com/nodejs/node/commit/ea4f19aaa7)] - **quic**: use arena allocation for packets (James M Snell) [#62589](https://github.com/nodejs/node/pull/62589) +* \[[`21e9239e2a`](https://github.com/nodejs/node/commit/21e9239e2a)] - **quic**: fixup linting/formatting issues (James M Snell) [#62387](https://github.com/nodejs/node/pull/62387) +* \[[`edeed4303b`](https://github.com/nodejs/node/commit/edeed4303b)] - **quic**: update http3 impl details (James M Snell) [#62387](https://github.com/nodejs/node/pull/62387) +* \[[`7f3a85e6aa`](https://github.com/nodejs/node/commit/7f3a85e6aa)] - **quic**: fix a handful of bugs and missing functionality (James M Snell) [#62387](https://github.com/nodejs/node/pull/62387) +* \[[`45c1ebddf8`](https://github.com/nodejs/node/commit/45c1ebddf8)] - **quic**: copy options.certs buffer instead of detaching (Chengzhong Wu) [#61403](https://github.com/nodejs/node/pull/61403) +* \[[`a31a8ee680`](https://github.com/nodejs/node/commit/a31a8ee680)] - **quic**: reduce boilerplate and other minor cleanups (James M Snell) [#59342](https://github.com/nodejs/node/pull/59342) +* \[[`3be70ff43a`](https://github.com/nodejs/node/commit/3be70ff43a)] - **quic**: multiple fixups and updates (James M Snell) [#59342](https://github.com/nodejs/node/pull/59342) +* \[[`b91a93444c`](https://github.com/nodejs/node/commit/b91a93444c)] - **quic**: update more of the quic to the new compile guard (James M Snell) [#59342](https://github.com/nodejs/node/pull/59342) +* \[[`ca0080c164`](https://github.com/nodejs/node/commit/ca0080c164)] - **quic**: few additional small comment edits in cid.h (James M Snell) [#59342](https://github.com/nodejs/node/pull/59342) +* \[[`6553202d83`](https://github.com/nodejs/node/commit/6553202d83)] - **quic**: fixup NO\_ERROR macro conflict on windows (James M Snell) [#59381](https://github.com/nodejs/node/pull/59381) +* \[[`6df1508ac2`](https://github.com/nodejs/node/commit/6df1508ac2)] - **quic**: fixup windows coverage compile error (James M Snell) [#59381](https://github.com/nodejs/node/pull/59381) +* \[[`b2b0bf8b04`](https://github.com/nodejs/node/commit/b2b0bf8b04)] - **quic**: update the guard to check openssl version (James M Snell) [#59249](https://github.com/nodejs/node/pull/59249) +* \[[`5556b154bd`](https://github.com/nodejs/node/commit/5556b154bd)] - **quic**: start re-enabling quic with openssl 3.5 (James M Snell) [#59249](https://github.com/nodejs/node/pull/59249) +* \[[`2ca42c8263`](https://github.com/nodejs/node/commit/2ca42c8263)] - **repl**: keep reference count for `process.on('newListener')` (Anna Henningsen) [#61895](https://github.com/nodejs/node/pull/61895) +* \[[`2f37f9177f`](https://github.com/nodejs/node/commit/2f37f9177f)] - **sqlite**: use OneByte for ASCII text and internalize col names (Ali Hassan) [#61954](https://github.com/nodejs/node/pull/61954) +* \[[`3c96ae1b2f`](https://github.com/nodejs/node/commit/3c96ae1b2f)] - **sqlite**: add serialize() and deserialize() (Ali Hassan) [#62579](https://github.com/nodejs/node/pull/62579) +* \[[`be4d2f3a4c`](https://github.com/nodejs/node/commit/be4d2f3a4c)] - **sqlite**: enable Percentile extension (Jurj Andrei George) [#61295](https://github.com/nodejs/node/pull/61295) +* \[[`dafed453b2`](https://github.com/nodejs/node/commit/dafed453b2)] - **src**: clean up experimental flag variables (Antoine du Hamel) [#62759](https://github.com/nodejs/node/pull/62759) +* \[[`dca1e6aeea`](https://github.com/nodejs/node/commit/dca1e6aeea)] - **src**: expose help texts into node-config-schema.json (Pietro Marchini) [#58680](https://github.com/nodejs/node/pull/58680) +* \[[`28c4f44eb1`](https://github.com/nodejs/node/commit/28c4f44eb1)] - **src**: add permission support to config file (Marco Ippolito) [#60746](https://github.com/nodejs/node/pull/60746) +* \[[`f49175b220`](https://github.com/nodejs/node/commit/f49175b220)] - **src**: fix small compile warning in quic/streams.cc (James M Snell) [#60118](https://github.com/nodejs/node/pull/60118) +* \[[`c9d4a446d8`](https://github.com/nodejs/node/commit/c9d4a446d8)] - **src**: cleanup quic TransportParams class (James M Snell) [#59884](https://github.com/nodejs/node/pull/59884) +* \[[`99bb02fd9e`](https://github.com/nodejs/node/commit/99bb02fd9e)] - **src**: swap dotenv and config file parsing order (Marco Ippolito) [#63035](https://github.com/nodejs/node/pull/63035) +* \[[`ecb4d49b7b`](https://github.com/nodejs/node/commit/ecb4d49b7b)] - **src**: add missing \ for abort() declaration (Charles Kerr) [#63001](https://github.com/nodejs/node/pull/63001) +* \[[`b6219b6362`](https://github.com/nodejs/node/commit/b6219b6362)] - **src**: fix crash in GetErrorSource() for invalid using syntax (semimikoh) [#62770](https://github.com/nodejs/node/pull/62770) +* \[[`b5ca5ad4c5`](https://github.com/nodejs/node/commit/b5ca5ad4c5)] - **src**: simplify `TCPWrap::Connect` signature (Anna Henningsen) [#62929](https://github.com/nodejs/node/pull/62929) +* \[[`ef7ffce7cf`](https://github.com/nodejs/node/commit/ef7ffce7cf)] - **src**: use DCHECK in AsyncWrap::MakeCallback instead emiting a warning (Gerhard Stöbich) [#62795](https://github.com/nodejs/node/pull/62795) +* \[[`cd9890a5ab`](https://github.com/nodejs/node/commit/cd9890a5ab)] - **src**: fix MaybeStackBuffer char\_traits deprecation warning (om-ghante) [#62507](https://github.com/nodejs/node/pull/62507) +* \[[`c70ff44aee`](https://github.com/nodejs/node/commit/c70ff44aee)] - **src**: use context-free V8 message column getters (René) [#62778](https://github.com/nodejs/node/pull/62778) +* \[[`06c405f1d7`](https://github.com/nodejs/node/commit/06c405f1d7)] - **src**: coerce `spawnSync` args to string once (Antoine du Hamel) [#62633](https://github.com/nodejs/node/pull/62633) +* \[[`6151999ad6`](https://github.com/nodejs/node/commit/6151999ad6)] - **src**: use stack allocation for small string encoding (Ali Hassan) [#62431](https://github.com/nodejs/node/pull/62431) +* \[[`a71a4ac7a3`](https://github.com/nodejs/node/commit/a71a4ac7a3)] - **src**: add contextify interceptor debug logs (Chengzhong Wu) [#62460](https://github.com/nodejs/node/pull/62460) +* \[[`ad9a2909c2`](https://github.com/nodejs/node/commit/ad9a2909c2)] - **src**: workaround AIX libc++ std::filesystem bug (Richard Lau) [#62788](https://github.com/nodejs/node/pull/62788) +* \[[`7792f1ae47`](https://github.com/nodejs/node/commit/7792f1ae47)] - **stream**: copyedit `webstreams/adapter.js` (Antoine du Hamel) [#63034](https://github.com/nodejs/node/pull/63034) +* \[[`1397d8ce5c`](https://github.com/nodejs/node/commit/1397d8ce5c)] - **stream**: remove duplicated utility (Antoine du Hamel) [#63031](https://github.com/nodejs/node/pull/63031) +* \[[`ff86b1d64f`](https://github.com/nodejs/node/commit/ff86b1d64f)] - **stream**: simplify `setPromiseHandled` utility (Antoine du Hamel) [#63032](https://github.com/nodejs/node/pull/63032) +* \[[`24a078149a`](https://github.com/nodejs/node/commit/24a078149a)] - **stream**: validate ReadableStream.from iterator objects (Daeyeon Jeong) [#62911](https://github.com/nodejs/node/pull/62911) +* \[[`cfb1fa9680`](https://github.com/nodejs/node/commit/cfb1fa9680)] - **stream**: reject duplicate nested transferables (Daeyeon Jeong) [#62831](https://github.com/nodejs/node/pull/62831) +* \[[`d0c913758a`](https://github.com/nodejs/node/commit/d0c913758a)] - **stream**: ensuring cross-destruction in \_duplexify to prevent leaks (Daijiro Wachi) [#62824](https://github.com/nodejs/node/pull/62824) +* \[[`978f5c15d7`](https://github.com/nodejs/node/commit/978f5c15d7)] - **stream**: simplify `readableStreamFromIterable` (Antoine du Hamel) [#62651](https://github.com/nodejs/node/pull/62651) +* \[[`3527646ba5`](https://github.com/nodejs/node/commit/3527646ba5)] - **stream**: fix nested compose error propagation (Matteo Collina) [#62556](https://github.com/nodejs/node/pull/62556) +* \[[`dfb9edef4f`](https://github.com/nodejs/node/commit/dfb9edef4f)] - **stream**: allow shared array buffer sources in writable webstream adapter (René) [#62163](https://github.com/nodejs/node/pull/62163) +* \[[`f00cdab627`](https://github.com/nodejs/node/commit/f00cdab627)] - **stream**: simplify `createPromiseCallback` (Antoine du Hamel) [#62650](https://github.com/nodejs/node/pull/62650) +* \[[`3ed783535f`](https://github.com/nodejs/node/commit/3ed783535f)] - **stream**: fix writev unhandled rejection in fromWeb (sangwook) [#62297](https://github.com/nodejs/node/pull/62297) +* \[[`29b196694c`](https://github.com/nodejs/node/commit/29b196694c)] - **stream**: noop pause/resume on destroyed streams (Robert Nagy) [#62557](https://github.com/nodejs/node/pull/62557) +* \[[`d73dbb9fc8`](https://github.com/nodejs/node/commit/d73dbb9fc8)] - **stream**: refactor duplexify to be less suceptible to prototype pollution (Antoine du Hamel) [#62559](https://github.com/nodejs/node/pull/62559) +* \[[`6f37f7e240`](https://github.com/nodejs/node/commit/6f37f7e240)] - **(SEMVER-MINOR)** **stream**: propagate destruction in duplexPair (Ahmed Elhor) [#61098](https://github.com/nodejs/node/pull/61098) +* \[[`b8816580e9`](https://github.com/nodejs/node/commit/b8816580e9)] - **test**: generate `localstorage.db` in a temp dir (Chengzhong Wu) [#62660](https://github.com/nodejs/node/pull/62660) +* \[[`31a863fd29`](https://github.com/nodejs/node/commit/31a863fd29)] - **test**: update WPT for url to 258f285de0 (Node.js GitHub Bot) [#63087](https://github.com/nodejs/node/pull/63087) +* \[[`d0d19bd8e3`](https://github.com/nodejs/node/commit/d0d19bd8e3)] - **test**: update WPT for streams to f8f26a372f (Node.js GitHub Bot) [#62864](https://github.com/nodejs/node/pull/62864) +* \[[`f50ac5bc78`](https://github.com/nodejs/node/commit/f50ac5bc78)] - **test**: improve config-file permission test coverage (Rafael Gonzaga) [#60929](https://github.com/nodejs/node/pull/60929) +* \[[`a0f90000f4`](https://github.com/nodejs/node/commit/a0f90000f4)] - **test**: export isRiscv64 from common module (Jamie Magee) [#62609](https://github.com/nodejs/node/pull/62609) +* \[[`da4dd8646f`](https://github.com/nodejs/node/commit/da4dd8646f)] - **test**: normalize known inspector crash as completion (Joyee Cheung) [#62851](https://github.com/nodejs/node/pull/62851) +* \[[`b7fdd94a4c`](https://github.com/nodejs/node/commit/b7fdd94a4c)] - **test**: account for RFC 7919 FFDHE negotiation in OpenSSL 4.0 (Filip Skokan) [#62805](https://github.com/nodejs/node/pull/62805) +* \[[`375a993aaf`](https://github.com/nodejs/node/commit/375a993aaf)] - **test**: skip tls-deprecated secp256k1 on OpenSSL 4.0 (Filip Skokan) [#62805](https://github.com/nodejs/node/pull/62805) +* \[[`698d8287d1`](https://github.com/nodejs/node/commit/698d8287d1)] - **test**: use an always invalid cipher and cover OpenSSL 4.0 behaviours (Filip Skokan) [#62805](https://github.com/nodejs/node/pull/62805) +* \[[`036bc6f300`](https://github.com/nodejs/node/commit/036bc6f300)] - **test**: use valid DER OCSP responses (Filip Skokan) [#62805](https://github.com/nodejs/node/pull/62805) +* \[[`3aa9938da8`](https://github.com/nodejs/node/commit/3aa9938da8)] - **test**: skip test-tls-error-stack when engines are unsupported (Filip Skokan) [#62805](https://github.com/nodejs/node/pull/62805) +* \[[`947f1ae246`](https://github.com/nodejs/node/commit/947f1ae246)] - **test**: accept renamed OpenSSL 4.0 error code and reason (Filip Skokan) [#62805](https://github.com/nodejs/node/pull/62805) +* \[[`afdd355622`](https://github.com/nodejs/node/commit/afdd355622)] - **test**: update test/addons/openssl-binding for OpenSSL 4.0 (Filip Skokan) [#62805](https://github.com/nodejs/node/pull/62805) +* \[[`8637524a99`](https://github.com/nodejs/node/commit/8637524a99)] - **test**: mark test-snapshot-reproducible flaky (Filip Skokan) [#62808](https://github.com/nodejs/node/pull/62808) +* \[[`c22d34134b`](https://github.com/nodejs/node/commit/c22d34134b)] - **test**: check contextify contextual store behavior in strict mode (René) [#62571](https://github.com/nodejs/node/pull/62571) +* \[[`0b4e0d3c94`](https://github.com/nodejs/node/commit/0b4e0d3c94)] - **test**: update tls junk data error expectations (Filip Skokan) [#62629](https://github.com/nodejs/node/pull/62629) +* \[[`85d83c2cdb`](https://github.com/nodejs/node/commit/85d83c2cdb)] - **test**: ensure WPT report is in out/wpt (Filip Skokan) [#62637](https://github.com/nodejs/node/pull/62637) +* \[[`9e21711c60`](https://github.com/nodejs/node/commit/9e21711c60)] - **test**: improve WPT runner summary (Filip Skokan) [#62636](https://github.com/nodejs/node/pull/62636) +* \[[`e04e2c9ac1`](https://github.com/nodejs/node/commit/e04e2c9ac1)] - **test**: skip url WPT subtests instead of modifying test script (Filip Skokan) [#62635](https://github.com/nodejs/node/pull/62635) +* \[[`7b1211f88c`](https://github.com/nodejs/node/commit/7b1211f88c)] - **test**: capture negative utimes mtime at call time (Yuya Inoue) [#62490](https://github.com/nodejs/node/pull/62490) +* \[[`f1a6e9fcc7`](https://github.com/nodejs/node/commit/f1a6e9fcc7)] - **test**: allow skipping individual WPT subtests (Filip Skokan) [#62517](https://github.com/nodejs/node/pull/62517) +* \[[`23f927542e`](https://github.com/nodejs/node/commit/23f927542e)] - **test**: use on-disk fixture for test-npm-install (Joyee Cheung) [#62584](https://github.com/nodejs/node/pull/62584) +* \[[`4739c45879`](https://github.com/nodejs/node/commit/4739c45879)] - **test**: update WPT for url to 7a3645b79a (Node.js GitHub Bot) [#62591](https://github.com/nodejs/node/pull/62591) +* \[[`f68189b839`](https://github.com/nodejs/node/commit/f68189b839)] - **test\_runner**: add `testId` to test events (Moshe Atlow) [#62772](https://github.com/nodejs/node/pull/62772) +* \[[`5c2770446e`](https://github.com/nodejs/node/commit/5c2770446e)] - **test\_runner**: publish to TracingChannel for OTel instrumentation (Moshe Atlow) [#62502](https://github.com/nodejs/node/pull/62502) +* \[[`d14029be7f`](https://github.com/nodejs/node/commit/d14029be7f)] - **(SEMVER-MINOR)** **test\_runner**: support test order randomization (Pietro Marchini) [#61747](https://github.com/nodejs/node/pull/61747) +* \[[`3f74a58979`](https://github.com/nodejs/node/commit/3f74a58979)] - **test\_runner**: update node-config-schema (Pietro Marchini) [#58680](https://github.com/nodejs/node/pull/58680) +* \[[`60c83f6199`](https://github.com/nodejs/node/commit/60c83f6199)] - **test\_runner**: fix failing suite hooks when marked with `todo` (Moshe Atlow) [#63097](https://github.com/nodejs/node/pull/63097) +* \[[`d142c584cd`](https://github.com/nodejs/node/commit/d142c584cd)] - **(SEMVER-MINOR)** **test\_runner**: align mock timeout api (sangwook) [#62820](https://github.com/nodejs/node/pull/62820) +* \[[`3e72065ed6`](https://github.com/nodejs/node/commit/3e72065ed6)] - **test\_runner**: fix suite rerun edge case (Moshe Atlow) [#62860](https://github.com/nodejs/node/pull/62860) +* \[[`01a9552585`](https://github.com/nodejs/node/commit/01a9552585)] - **(SEMVER-MINOR)** **test\_runner**: add mock-timers support for AbortSignal.timeout (DeveloperViraj) [#60751](https://github.com/nodejs/node/pull/60751) +* \[[`dd43efffa6`](https://github.com/nodejs/node/commit/dd43efffa6)] - **test\_runner**: add passed, attempt, and diagnostic to SuiteContext (Moshe Atlow) [#62504](https://github.com/nodejs/node/pull/62504) +* \[[`a12dc445cc`](https://github.com/nodejs/node/commit/a12dc445cc)] - **tools**: add a check for clean git tree after tests (Antoine du Hamel) [#62661](https://github.com/nodejs/node/pull/62661) +* \[[`5b49178375`](https://github.com/nodejs/node/commit/5b49178375)] - **tools**: use LTS Node.js in notify-on-push workflow (Nenad Spasenic) [#63084](https://github.com/nodejs/node/pull/63084) +* \[[`5a93bde5bb`](https://github.com/nodejs/node/commit/5a93bde5bb)] - **tools**: update gr2m/create-or-update-pull-request-action to v1.10.1 (Mike McCready) [#63065](https://github.com/nodejs/node/pull/63065) +* \[[`b133019d19`](https://github.com/nodejs/node/commit/b133019d19)] - **tools**: simplify `update-undici.sh` (Antoine du Hamel) [#63044](https://github.com/nodejs/node/pull/63044) +* \[[`04d3538074`](https://github.com/nodejs/node/commit/04d3538074)] - **tools**: do not run `test-linux` on unrelated tools changes (Antoine du Hamel) [#63037](https://github.com/nodejs/node/pull/63037) +* \[[`4d396ac4a5`](https://github.com/nodejs/node/commit/4d396ac4a5)] - **tools**: bump the eslint group in /tools/eslint with 4 updates (dependabot\[bot]) [#62848](https://github.com/nodejs/node/pull/62848) +* \[[`9354bf40e7`](https://github.com/nodejs/node/commit/9354bf40e7)] - **tools**: update gyp-next to 0.22.1 (Node.js GitHub Bot) [#62961](https://github.com/nodejs/node/pull/62961) +* \[[`c23db1ca85`](https://github.com/nodejs/node/commit/c23db1ca85)] - **tools**: fix commit linter for semver-major release proposals (Antoine du Hamel) [#62993](https://github.com/nodejs/node/pull/62993) +* \[[`6e097ee3f1`](https://github.com/nodejs/node/commit/6e097ee3f1)] - **tools**: consolidate and simplify .editorconfig deps section (Daijiro Wachi) [#62887](https://github.com/nodejs/node/pull/62887) +* \[[`a47ea6d6ea`](https://github.com/nodejs/node/commit/a47ea6d6ea)] - **tools**: set bot as author of tools-deps-update PRs (Antoine du Hamel) [#62856](https://github.com/nodejs/node/pull/62856) +* \[[`00e86f0471`](https://github.com/nodejs/node/commit/00e86f0471)] - **tools**: bump brace-expansion from 5.0.4 to 5.0.5 in /tools/eslint (dependabot\[bot]) [#62458](https://github.com/nodejs/node/pull/62458) +* \[[`cd7e262e75`](https://github.com/nodejs/node/commit/cd7e262e75)] - **tools**: bump brace-expansion in /tools/clang-format (dependabot\[bot]) [#62467](https://github.com/nodejs/node/pull/62467) +* \[[`bfc1319bc8`](https://github.com/nodejs/node/commit/bfc1319bc8)] - **tools**: exclude @node-core/doc-kit from dependabot cooldown (Levi Zim) [#62775](https://github.com/nodejs/node/pull/62775) +* \[[`a932fbd10b`](https://github.com/nodejs/node/commit/a932fbd10b)] - **tools**: re-enable undici WPTs in daily wpt.fyi job (Filip Skokan) [#62677](https://github.com/nodejs/node/pull/62677) +* \[[`f7bd9e3055`](https://github.com/nodejs/node/commit/f7bd9e3055)] - **tools**: update gyp-next to 0.22.0 (Node.js GitHub Bot) [#62697](https://github.com/nodejs/node/pull/62697) +* \[[`c400d46d87`](https://github.com/nodejs/node/commit/c400d46d87)] - **tools**: improve backport review script (Antoine du Hamel) [#62573](https://github.com/nodejs/node/pull/62573) +* \[[`be23b75814`](https://github.com/nodejs/node/commit/be23b75814)] - **tools**: improve output for unexpected passes in WTP tests (Antoine du Hamel) [#62587](https://github.com/nodejs/node/pull/62587) +* \[[`609c013ece`](https://github.com/nodejs/node/commit/609c013ece)] - **tools**: revert OpenSSL update workflow to ubuntu-latest (Richard Lau) [#62627](https://github.com/nodejs/node/pull/62627) +* \[[`81bac1ebfd`](https://github.com/nodejs/node/commit/81bac1ebfd)] - **tools**: bump the eslint group in /tools/eslint with 2 updates (dependabot\[bot]) [#62552](https://github.com/nodejs/node/pull/62552) +* \[[`1fee26522d`](https://github.com/nodejs/node/commit/1fee26522d)] - **tools**: allow triagers to queue a PR for CI until it's reviewed (Antoine du Hamel) [#62524](https://github.com/nodejs/node/pull/62524) +* \[[`332088f929`](https://github.com/nodejs/node/commit/332088f929)] - **tools**: do not run `commit-lint` on release proposals (Antoine du Hamel) [#62523](https://github.com/nodejs/node/pull/62523) +* \[[`9a25fc8a4d`](https://github.com/nodejs/node/commit/9a25fc8a4d)] - **url**: process crash via malformed UNC hostname in pathToFileURL() (Nicola Del Gobbo) [#62574](https://github.com/nodejs/node/pull/62574) +* \[[`7bd08ff60a`](https://github.com/nodejs/node/commit/7bd08ff60a)] - **url**: optimize URLSearchParams set/delete duplicate handling (Gürgün Dayıoğlu) [#62266](https://github.com/nodejs/node/pull/62266) +* \[[`2d636388fa`](https://github.com/nodejs/node/commit/2d636388fa)] - **url**: align default argument handling for URLPattern with webidl (Filip Skokan) [#62719](https://github.com/nodejs/node/pull/62719) +* \[[`00705a459a`](https://github.com/nodejs/node/commit/00705a459a)] - **(SEMVER-MINOR)** **util**: colorize text with hex colors (Guilherme Araújo) [#61556](https://github.com/nodejs/node/pull/61556) +* \[[`0e2adb3e45`](https://github.com/nodejs/node/commit/0e2adb3e45)] - **watch**: track worker entry files in watch mode (SudhansuBandha) [#62368](https://github.com/nodejs/node/pull/62368) +* \[[`c58fe38211`](https://github.com/nodejs/node/commit/c58fe38211)] - **watch**: fix --env-file-if-exists crashing on linux if the file is missing (Efe) [#61870](https://github.com/nodejs/node/pull/61870) + ## 2026-04-15, Version 24.15.0 'Krypton' (LTS), @aduh95 From d92ee51aa6dc44c7026948514ff058913b9dfb75 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Thu, 21 May 2026 09:50:23 -0400 Subject: [PATCH 37/83] src: expose `node::RegisterContext` to make a node managed context Signed-off-by: Chengzhong Wu PR-URL: https://github.com/nodejs/node/pull/62322 Reviewed-By: Joyee Cheung --- src/api/environment.cc | 13 ++++ src/env.h | 2 + src/node.h | 14 ++++ test/addons/new-context-inspector/binding.cc | 69 +++++++++++++++++++ test/addons/new-context-inspector/binding.gyp | 9 +++ .../new-context-inspector/test-inspector.js | 51 ++++++++++++++ test/addons/new-context-inspector/test.js | 18 +++++ 7 files changed, 176 insertions(+) create mode 100644 test/addons/new-context-inspector/binding.cc create mode 100644 test/addons/new-context-inspector/binding.gyp create mode 100644 test/addons/new-context-inspector/test-inspector.js create mode 100644 test/addons/new-context-inspector/test.js diff --git a/src/api/environment.cc b/src/api/environment.cc index 25657d99bddaa3..c3fd1e58373516 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -2,6 +2,7 @@ #if HAVE_OPENSSL #include "crypto/crypto_util.h" #endif // HAVE_OPENSSL +#include "env.h" #include "env_properties.h" #include "node.h" #include "node_builtins.h" @@ -1053,6 +1054,18 @@ Maybe InitializeContext(Local context) { return Just(true); } +void RegisterContext(Environment* env, + v8::Local context, + std::string_view name, + std::string_view origin) { + ContextInfo info{std::string(name), std::string(origin)}; + env->AssignToContext(context, nullptr, info); +} + +void UnregisterContext(Environment* env, v8::Local context) { + env->UnassignFromContext(context); +} + uv_loop_t* GetCurrentEventLoop(Isolate* isolate) { HandleScope handle_scope(isolate); Local context = isolate->GetCurrentContext(); diff --git a/src/env.h b/src/env.h index 616f6e7d04109a..61512d9494ff61 100644 --- a/src/env.h +++ b/src/env.h @@ -257,6 +257,8 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer { struct ContextInfo { explicit ContextInfo(const std::string& name) : name(name) {} + ContextInfo(const std::string& name, const std::string& origin) + : name(name), origin(origin) {} const std::string name; std::string origin; bool is_default = false; diff --git a/src/node.h b/src/node.h index eba7b8698187b1..e25fe19c9ab30c 100644 --- a/src/node.h +++ b/src/node.h @@ -563,6 +563,8 @@ NODE_EXTERN v8::Isolate* NewIsolate( const IsolateSettings& settings = {}); // Creates a new context with Node.js-specific tweaks. +// Call `RegisterContext` after the context been created to register +// the context with Node.js specific setups like the inspector. NODE_EXTERN v8::Local NewContext( v8::Isolate* isolate, v8::Local object_template = @@ -572,6 +574,18 @@ NODE_EXTERN v8::Local NewContext( // Return value indicates success of operation NODE_EXTERN v8::Maybe InitializeContext(v8::Local context); +// Associate the context with the given Environment. This registers the context +// as known to Node.js, makes it available to the inspector. This also registers +// Node.js promise hooks on the context. +NODE_EXTERN void RegisterContext(Environment* env, + v8::Local context, + std::string_view name = "", + std::string_view origin = ""); +// Unregister the context. Call this when the embedder finished all work with +// this context. +NODE_EXTERN void UnregisterContext(Environment* env, + v8::Local context); + // If `platform` is passed, it will be used to register new Worker instances. // It can be `nullptr`, in which case creating new Workers inside of // Environments that use this `IsolateData` will not work. diff --git a/test/addons/new-context-inspector/binding.cc b/test/addons/new-context-inspector/binding.cc new file mode 100644 index 00000000000000..b5a025b18d0df6 --- /dev/null +++ b/test/addons/new-context-inspector/binding.cc @@ -0,0 +1,69 @@ +#include +#include + +namespace { + +using v8::Context; +using v8::FunctionCallbackInfo; +using v8::HandleScope; +using v8::Isolate; +using v8::Local; +using v8::Object; +using v8::Script; +using v8::String; +using v8::Value; + +void MakeContext(const FunctionCallbackInfo& args) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope handle_scope(isolate); + Local context = isolate->GetCurrentContext(); + node::Environment* env = node::GetCurrentEnvironment(context); + assert(env); + + // Create a new context with Node.js-specific setup. + v8::MaybeLocal maybe_context = node::NewContext(isolate); + v8::Local new_context; + if (!maybe_context.ToLocal(&new_context)) { + return; + } + node::RegisterContext(env, new_context, "Addon Context", "addon://about"); + + // Return the global proxy object. + args.GetReturnValue().Set(new_context->Global()); +} + +void RunInContext(const FunctionCallbackInfo& args) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope handle_scope(isolate); + assert(args.Length() == 2); + + assert(args[0]->IsObject()); + Local global_proxy = args[0].As(); + v8::MaybeLocal maybe_context = global_proxy->GetCreationContext(); + v8::Local new_context; + if (!maybe_context.ToLocal(&new_context)) { + return; + } + Context::Scope context_scope(new_context); + + assert(args[1]->IsString()); + Local source = args[1].As(); + Local