Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
0566799
deps: V8: backport 1c3e018e7d48
Renegade334 Jun 24, 2025
7ab13b7
test: don't use expose internals in test-http-outgoing-buffer.js
nektro Jul 28, 2025
4a907bd
src: add percentage support to --max-old-space-size
Asaf-Federman Jul 28, 2025
bd68fbd
worker: add cpuUsage for worker
theanarkh Jul 28, 2025
564e604
test: make test-inspector-network-resource sequential
islandryu Jul 28, 2025
5a98bff
doc: format safely for `doc-kit`
avivkeller Jul 28, 2025
31a9283
doc: add note on process memoryUsage
fengmk2 Jul 11, 2025
cff3725
doc: fix typo in `test/common/README.md`
ri7116 Jul 28, 2025
33728cb
src: add nullptr checks in `StreamPipe::New`
wooffie Jul 28, 2025
aeb4de5
fs: port SonicBoom module to fs module as Utf8Stream
jasnell Jun 30, 2025
713c70c
test_runner: remove unused callee convertion
himself65 Jul 26, 2025
6a47ff4
src: clear all linked module caches once instantiated
legendecas Jul 29, 2025
7b94982
tools: allow selecting test subsystems with numbers in their names
RaisinTen Jul 29, 2025
0fb005a
http2: set Http2Stream#sentHeaders for raw headers
RaisinTen Jul 29, 2025
41978ad
deps: V8: backport 493cb53691be
legendecas Jun 30, 2025
8c609be
benchmark: add calibrate-n script
RafaelGSS Jul 29, 2025
e2fb4ca
fs: correct error message when FileHandle is transferred
himself65 Jul 29, 2025
848e49c
benchmark: add fs warmup to writefile-promises
brunocroh Jul 29, 2025
5b2363b
lib: prefer AsyncIteratorPrototype primordial
Renegade334 Jul 29, 2025
31a46fd
doc: add path.join and path.normalize clarification
RafaelGSS Jul 30, 2025
22d4683
src: added CHECK_NOT_NULL check for multiple eq_wrap_async
F3lixTheCat Jul 31, 2025
84c3513
worker: implements nits in Web Locks code
aduh95 Jul 31, 2025
1e2c52f
doc: add manpage entry for --use-system-ca
joyeecheung Jul 31, 2025
a056dd3
doc: add WDYT to glossary
btea Aug 1, 2025
2990f17
fs: fix glob TypeError on restricted dirs
Sylphy-0xd3ac Aug 1, 2025
dab7f6b
tools: check for std::vector<v8::Local> in lint
Aditi-1400 Aug 1, 2025
1e37eab
node-api: reword "implementation in an alternative VM" as implementable
legendecas Aug 1, 2025
c89b67e
lib: add type names in source mapped stack traces
legendecas Aug 1, 2025
d69f3ee
meta: add nodejs/path to path files
RafaelGSS Aug 1, 2025
c144d69
lib: docs deprecate _http_*
bjohansebas Aug 2, 2025
244d0c3
test: deflake stream-readable-to-web test
Ethan-Arrowood Aug 2, 2025
76bc4d6
typings: improve internal binding types
targos Aug 2, 2025
95e9cab
doc: clarify release candidate stability index
panva Aug 2, 2025
4ee4679
lib: use validateString
hotpineapple Aug 2, 2025
a2b72c2
meta: add tsc and build team as codeowners building.md
RafaelGSS Aug 2, 2025
f9f3dc9
test: add known issue test for fs.cpSync dereference bug
jasnell Aug 2, 2025
e91b54d
lib: handle superscript variants on windows device
RafaelGSS Aug 2, 2025
d140c37
doc: clarify the need of compiler compatible with c++20
RafaelGSS Aug 2, 2025
46527e8
doc: correct orthography `eg.` → `e.g.`
JakobJingleheimer Aug 3, 2025
41bcf5f
test: update WPT resources,WebCryptoAPI,webstorage
panva Aug 3, 2025
0eb5962
meta: add mailmap entry for aditi-1400
Aditi-1400 Aug 3, 2025
1e5f632
src: use C++20 `contains()` method
iknoom Jul 31, 2025
e79c93a
http: add server.keepAliveTimeoutBuffer option
haramj Aug 4, 2025
2013045
zlib: add dictionary support to zstdCompress and zstdDecompress
lluisemper Aug 4, 2025
db24174
deps: update sqlite to 3.50.4
nodejs-github-bot Aug 5, 2025
95b8b7e
domain: remove deprecated API call
himself65 Aug 5, 2025
a312e70
crypto: prepare webcrypto key import/export for modern algorithms
panva Aug 5, 2025
8686b80
src: remove unused DSAKeyExportJob
panva Aug 5, 2025
eecd327
worker: add name for worker
theanarkh Aug 5, 2025
3c88b76
lib: restructure assert to become a class
miguelmarcondesf Aug 5, 2025
f834a6b
deps: update undici to 7.13.0
nodejs-github-bot Aug 5, 2025
e3e4897
doc: run license-builder
github-actions[bot] Aug 6, 2025
8341916
doc: fix grammar in global dispatcher usage
Juneezee Aug 6, 2025
41b4f4d
meta: clarify pr objection process further
jasnell Aug 6, 2025
38aedfb
crypto: support ML-DSA KeyObject, sign, and verify
panva Aug 6, 2025
42ef814
src: warn about FastOneByteString invalidation
jasnell Jul 29, 2025
72cfff1
doc: fix missing reference links for server.keepAliveTimeoutBuffer
wlgh1553 Aug 7, 2025
e9c6636
src: mark realm leaf classes final
addaleax Aug 4, 2025
fa70f1a
deps: support madvise(3C) across ALL illumos revisions
danmcd Aug 7, 2025
33b06df
deps: upgrade openssl sources to openssl-3.5.2
nodejs-github-bot Aug 5, 2025
8d9ceea
deps: update archs files for openssl-3.5.2
nodejs-github-bot Aug 5, 2025
f748457
assert: change utils to use index instead of for...of
JinhyeokFang Aug 7, 2025
c6911f0
lib: do not modify prototype deprecated asyncResource
RafaelGSS Jul 24, 2025
6a3bf77
build: fix node_use_sqlite for GN builds
codebytere Aug 9, 2025
16bbcd8
typings: improve internal binding types
meteorqz6 Aug 9, 2025
e4ca30e
tools: disable nullability-completeness warnings
targos Aug 9, 2025
47543a7
lib: handle windows reserved device names on UNC
RafaelGSS Aug 9, 2025
a271ae4
doc: fix Pbkdf2Params hash attribute heading
panva Aug 9, 2025
319df38
test,crypto: skip unsupported ciphers
codebytere Aug 9, 2025
fd61588
doc: rename x509.extKeyUsage to x509.keyUsage
panva Aug 9, 2025
3a7c2c3
deps: update ada to 3.2.7
nodejs-github-bot Aug 10, 2025
64add63
src: use simdjson to parse SEA configuration
joyeecheung Aug 1, 2025
471fe71
cli: add NODE_USE_SYSTEM_CA=1
joyeecheung Aug 10, 2025
7e10f95
test: split test-fs-cp.js
joyeecheung Aug 10, 2025
d2183d8
lib: optimize writable stream buffer clearing
ri7116 Aug 11, 2025
fb0a6fb
test: exclude mock from coverage
islandryu Aug 11, 2025
e055539
lib: add trace-sigint APIs
theanarkh Aug 11, 2025
269cd16
benchmark: remove deprecated _extend from benchmark
RafaelGSS Aug 11, 2025
7c189d4
test: deflake sequential/test-tls-session-timeout
joyeecheung Aug 11, 2025
09dc7a5
2025-08-14, Version 24.6.0 (Current)
nodejs-github-bot Aug 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
/doc/contributing/**/* @nodejs/tsc
/GOVERNANCE.md @nodejs/tsc
/SECURITY.md @nodejs/tsc
/BUILDING.md @nodejs/build @nodejs/tsc
/LICENSE @nodejs/tsc
/onboarding.md @nodejs/tsc

Expand Down Expand Up @@ -223,3 +224,8 @@
/lib/internal/inspector/* @nodejs/inspector
/lib/internal/inspector_* @nodejs/inspector
/lib/inspector.js @nodejs/inspector

# path
/lib/path.js @nodejs/path
/lib/path/* @nodejs/path
/test/parallel/test-path-* @nodejs/path
1 change: 1 addition & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Abdirahim Musse <[email protected]> <[email protected]
Abe Fettig <[email protected]> <[email protected]>
Abhimanyu Vashisht <[email protected]>
Adam Langley <[email protected]> <[email protected]>
Aditi Singh <[email protected]>
Akhil Marsonya <[email protected]>
Akhil Marsonya <[email protected]> <[email protected]>
Akito Ito <[email protected]> <[email protected]>
Expand Down
5 changes: 5 additions & 0 deletions BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@ export CXX=g++-12
make -j4
```

> \[!IMPORTANT]
> If you face a compilation error during this process such as
> `error: no matching conversion for functional-style cast from 'unsigned int' to 'TypeIndex'`
> Make sure to use a `g++` or `clang` version compatible with C++20.

We can speed up the builds by using [Ninja](https://ninja-build.org/). For more
information, see
[Building Node.js with Ninja](doc/contributing/building-node-with-ninja.md).
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ release.
</tr>
<tr>
<td valign="top">
<b><a href="doc/changelogs/CHANGELOG_V24.md#24.5.0">24.5.0</a></b><br/>
<b><a href="doc/changelogs/CHANGELOG_V24.md#24.6.0">24.6.0</a></b><br/>
<a href="doc/changelogs/CHANGELOG_V24.md#24.5.0">24.5.0</a><br/>
<a href="doc/changelogs/CHANGELOG_V24.md#24.4.1">24.4.1</a><br/>
<a href="doc/changelogs/CHANGELOG_V24.md#24.4.0">24.4.0</a><br/>
<a href="doc/changelogs/CHANGELOG_V24.md#24.3.0">24.3.0</a><br/>
Expand Down
25 changes: 25 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -2639,3 +2639,28 @@ The externally maintained libraries used by Node.js are:
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

- sonic-boom, located at lib/internal/streams/fast-utf8-stream.js, is licensed as follows:
"""
MIT License

Copyright (c) 2017 Matteo Collina

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
5 changes: 5 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ then untrusted input must not lead to arbitrary JavaScript code execution.
See <https://nodejs.org/api/modules.html#all-together>.
* The `node:wasi` module does not currently provide the comprehensive file
system security properties provided by some WASI runtimes.
* The execution path is trusted. Additionally, Node.js path manipulation functions
such as `path.join()` and `path.normalize()` trust their input. Reports about issues
related to these functions that rely on unsanitized input are not considered vulnerabilities
requiring CVEs, as it's the user's responsibility to sanitize path inputs according to
their security requirements.

Any unexpected behavior from the data manipulation from Node.js Internal
functions may be considered a vulnerability if they are exploitable via
Expand Down
292 changes: 292 additions & 0 deletions benchmark/calibrate-n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
'use strict';

const path = require('node:path');
const { fork } = require('node:child_process');
const fs = require('node:fs');
const { styleText } = require('node:util');

const DEFAULT_RUNS = 30; // Number of runs for each n value
const CV_THRESHOLD = 0.05; // 5% coefficient of variation threshold
const MAX_N_INCREASE = 6; // Maximum number of times to increase n (10**6)
const INCREASE_FACTOR = 10; // Factor by which to increase n

const args = process.argv.slice(2);
if (args.length === 0) {
console.log(`
Usage: node calibrate-n.js [options] <benchmark_path>

Options:
--runs=N Number of runs for each n value (default: ${DEFAULT_RUNS})
--cv-threshold=N Target coefficient of variation threshold (default: ${CV_THRESHOLD})
--max-increases=N Maximum number of n increases to try (default: ${MAX_N_INCREASE})
--start-n=N Initial n value to start with (default: autodetect)
--increase=N Factor by which to increase n (default: ${INCREASE_FACTOR})

Example:
node calibrate-n.js buffers/buffer-compare.js
node calibrate-n.js --runs=10 --cv-threshold=0.02 buffers/buffer-compare.js
`);
process.exit(1);
}

// Extract options
let benchmarkPath;
let runs = DEFAULT_RUNS;
let cvThreshold = CV_THRESHOLD;
let maxIncreases = MAX_N_INCREASE;
let startN = 10;
let increaseFactor = INCREASE_FACTOR;

for (const arg of args) {
if (arg.startsWith('--runs=')) {
runs = parseInt(arg.substring(7), 10);
} else if (arg.startsWith('--cv-threshold=')) {
cvThreshold = parseFloat(arg.substring(14));
} else if (arg.startsWith('--max-increases=')) {
maxIncreases = parseInt(arg.substring(15), 10);
if (isNaN(maxIncreases)) {
console.error(`Error: Invalid value for --max-increases. Using default: ${MAX_N_INCREASE}`);
maxIncreases = MAX_N_INCREASE;
}
} else if (arg.startsWith('--start-n=')) {
startN = parseInt(arg.substring(10), 10);
if (isNaN(startN)) {
console.error(`Error: Invalid value for --start-n. Using default: 10`);
startN = 10;
}
} else if (arg.startsWith('--increase=')) {
increaseFactor = parseInt(arg.substring(11), 10);
if (isNaN(increaseFactor)) {
console.error(`Error: Invalid value for --increase. Using default: ${INCREASE_FACTOR}`);
increaseFactor = INCREASE_FACTOR;
}
} else {
benchmarkPath = arg;
}
}

if (!benchmarkPath) {
console.error('Error: No benchmark path specified');
process.exit(1);
}

const fullBenchmarkPath = path.resolve(benchmarkPath);
if (!fs.existsSync(fullBenchmarkPath)) {
console.error(`Error: Benchmark file not found: ${fullBenchmarkPath}`);
process.exit(1);
}

function calculateStats(values) {
const mean = values.reduce((sum, val) => sum + val, 0) / values.length;

const squaredDiffs = values.map((val) => {
const diff = val - mean;
const squared = diff ** 2;
return squared;
});

const variance = squaredDiffs.reduce((sum, val) => sum + val, 0) / values.length;
const stdDev = Math.sqrt(variance);
const cv = stdDev / mean;

return { mean, stdDev, cv, variance };
}

function runBenchmark(n) {
return new Promise((resolve, reject) => {
const child = fork(
fullBenchmarkPath,
[`n=${n}`],
{ stdio: ['inherit', 'pipe', 'inherit', 'ipc'] },
);

const results = [];
child.on('message', (data) => {
if (data.type === 'report' && data.rate && data.conf) {
results.push({
rate: data.rate,
conf: data.conf,
});
}
});

child.on('close', (code) => {
if (code !== 0) {
reject(new Error(`Benchmark exited with code ${code}`));
} else {
resolve(results);
}
});
});
}

async function main(n = startN) {
let increaseCount = 0;
let bestN = n;
let bestCV = Infinity;
let bestGroupStats = null;

console.log(`
--------------------------------------------------------
Benchmark: ${benchmarkPath}
--------------------------------------------------------
What we are trying to find: The optimal number of iterations (n)
that produces consistent benchmark results without wasting time.

How it works:
1. Run the benchmark multiple times with a specific n value
2. Group results by configuration
3. If overall CV is above 5% or any configuration has CV above 10%, increase n and try again

Configuration:
- Starting n: ${n.toLocaleString()} iterations
- Runs per n value: ${runs}
- Target CV threshold: ${cvThreshold * 100}% (lower CV = more stable results)
- Max increases: ${maxIncreases}
- Increase factor: ${increaseFactor}x`);

while (increaseCount < maxIncreases) {
console.log(`\nTesting with n=${n}:`);

const resultsData = [];
for (let i = 0; i < runs; i++) {
const results = await runBenchmark(n);
// Each run might return multiple results (one per configuration)
if (Array.isArray(results) && results.length > 0) {
resultsData.push(...results);
} else if (results) {
resultsData.push(results);
}
process.stdout.write('.');
}
process.stdout.write('\n');

const groupedResults = {};
resultsData.forEach((result) => {
if (!result || !result.conf) return;

const confKey = JSON.stringify(result.conf);
groupedResults[confKey] ||= {
conf: result.conf,
rates: [],
};

groupedResults[confKey].rates.push(result.rate);
});

const groupStats = [];
for (const [confKey, group] of Object.entries(groupedResults)) {
console.log(`\nConfiguration: ${JSON.stringify(group.conf)}`);

const stats = calculateStats(group.rates);
console.log(` CV: ${(stats.cv * 100).toFixed(2)}% (lower values mean more stable results)`);

const isStable = stats.cv <= cvThreshold;
console.log(` Stability: ${isStable ?
styleText(['bold', 'green'], '✓ Stable') :
styleText(['bold', 'red'], '✗ Unstable')}`);

groupStats.push({
confKey,
stats,
isStable,
});
}

if (groupStats.length > 0) {
// Check if any configuration has CV > 10% (too unstable)
const tooUnstableConfigs = groupStats.filter((g) => g.stats.cv > 0.10);

const avgCV = groupStats.reduce((sum, g) => sum + g.stats.cv, 0) / groupStats.length;
console.log(`\nOverall average CV: ${(avgCV * 100).toFixed(2)}%`);

const isOverallStable = avgCV < CV_THRESHOLD;
const hasVeryUnstableConfigs = tooUnstableConfigs.length > 0;

// Check if overall CV is below CV_THRESHOLD and no configuration has CV > 10%
if (isOverallStable && !hasVeryUnstableConfigs) {
console.log(styleText(['bold', 'green'], ` ✓ Overall CV is below 5% and no configuration has CV above 10%`));
} else {
if (!isOverallStable) {
console.log(styleText(['bold', 'red'], ` ✗ Overall CV (${(avgCV * 100).toFixed(2)}%) is above 5%`));
}
if (hasVeryUnstableConfigs) {
console.log(styleText(['bold', 'red'], ` ✗ ${tooUnstableConfigs.length} configuration(s) have CV above 10%`));
}
}

if (avgCV < bestCV || !bestGroupStats) {
bestN = n;
bestCV = avgCV;

bestGroupStats = [];
for (const group of Object.values(groupedResults)) {
if (group.rates.length >= 3) {
const stats = calculateStats(group.rates);
bestGroupStats.push({
conf: group.conf,
stats: stats,
isStable: stats.cv <= 0.10,
});
}
}
console.log(` → New best n: ${n} with average CV: ${(avgCV * 100).toFixed(2)}%`);
} else {
console.log(` → Current best n remains: ${bestN} with average CV: ${(bestCV * 100).toFixed(2)}%`);
}
}

// Check if we've reached acceptable stability based on new criteria
// 1. Overall CV should be below CV_THRESHOLD
// 2. No configuration should have a CV greater than 10%
const avgCV = groupStats.length > 0 ?
groupStats.reduce((sum, g) => sum + g.stats.cv, 0) / groupStats.length : Infinity;
const hasUnstableConfig = groupStats.some((g) => g.stats.cv > 0.10);
const isOverallStable = avgCV < CV_THRESHOLD;

if (isOverallStable && !hasUnstableConfig) {
console.log(`\n✓ Found optimal n=${n} (Overall CV=${(avgCV * 100).toFixed(2)}% < 5% and no configuration has CV > 10%)`);
console.log('\nFinal CV for each configuration:');
groupStats.forEach((g) => {
console.log(` ${JSON.stringify(groupedResults[g.confKey].conf)}: ${(g.stats.cv * 100).toFixed(2)}%`);
});

return n;
}

increaseCount++;
n *= increaseFactor;
}

if (increaseCount >= maxIncreases) {
const finalAvgCV = bestGroupStats && bestGroupStats.length > 0 ?
bestGroupStats.reduce((sum, g) => sum + g.stats.cv, 0) / bestGroupStats.length : Infinity;

console.log(`Maximum number of increases (${maxIncreases}) reached without achieving target stability`);
console.log(`Best n found: ${bestN} with average CV=${(finalAvgCV * 100).toFixed(2)}%`);
console.log(`\nCV by configuration at best n:`);

if (bestGroupStats) {
bestGroupStats.forEach((g) => {
if (g.conf) {
console.log(` ${JSON.stringify(g.conf)}: ${(g.stats.cv * 100).toFixed(2)}%`);
if (g.stats.cv > cvThreshold) {
console.log(` ⚠️ This configuration is above the target threshold of ${cvThreshold * 100}%`);
}
}
});
}
}

console.log(`
Recommendation: You might want to try increasing --max-increases to
continue testing with larger n values, or adjust --cv-threshold to
accept the current best result, or investigate if specific configurations
are contributing to instability.`);
return bestN;
}

main().catch((err) => {
console.error('Error:', err);
process.exit(1);
});
9 changes: 5 additions & 4 deletions benchmark/crypto/create-keyobject.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ function readKeyPair(publicKeyName, privateKeyName) {
}

const keyFixtures = {
ec: readKeyPair('ec_p256_public', 'ec_p256_private'),
rsa: readKeyPair('rsa_public_2048', 'rsa_private_2048'),
ed25519: readKeyPair('ed25519_public', 'ed25519_private'),
'ec': readKeyPair('ec_p256_public', 'ec_p256_private'),
'rsa': readKeyPair('rsa_public_2048', 'rsa_private_2048'),
'ed25519': readKeyPair('ed25519_public', 'ed25519_private'),
'ml-dsa-44': readKeyPair('ml_dsa_44_public', 'ml_dsa_44_private'),
};

const bench = common.createBenchmark(main, {
keyType: ['rsa', 'ec', 'ed25519'],
keyType: ['rsa', 'ec', 'ed25519', 'ml-dsa-44'],
keyFormat: ['pkcs8', 'spki', 'der-pkcs8', 'der-spki', 'jwk-public', 'jwk-private'],
n: [1e3],
});
Expand Down
Loading
Loading