diff --git a/.github/workflows/build-tarball.yml b/.github/workflows/build-tarball.yml
index 72b638cd0be1a2..0e4e54e2500f5e 100644
--- a/.github/workflows/build-tarball.yml
+++ b/.github/workflows/build-tarball.yml
@@ -46,13 +46,13 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up sccache
uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5
with:
- version: v0.8.0
+ version: v0.8.1
- name: Environment Information
run: npx envinfo
- name: Make tarball
@@ -64,7 +64,7 @@ jobs:
mkdir tarballs
mv *.tar.gz tarballs
- name: Upload tarball artifact
- uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
+ uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: tarballs
path: tarballs
@@ -76,13 +76,13 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up sccache
uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5
with:
- version: v0.8.0
+ version: v0.8.1
- name: Environment Information
run: npx envinfo
- name: Download tarball
diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml
index 929c7d0362f61e..f8bc1d979a647f 100644
--- a/.github/workflows/build-windows.yml
+++ b/.github/workflows/build-windows.yml
@@ -42,7 +42,7 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install deps
diff --git a/.github/workflows/coverage-linux-without-intl.yml b/.github/workflows/coverage-linux-without-intl.yml
index 757c479dbb564a..49ba0662d62b6f 100644
--- a/.github/workflows/coverage-linux-without-intl.yml
+++ b/.github/workflows/coverage-linux-without-intl.yml
@@ -50,13 +50,13 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up sccache
uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5
with:
- version: v0.8.0
+ version: v0.8.1
- name: Environment Information
run: npx envinfo
- name: Install gcovr
diff --git a/.github/workflows/coverage-linux.yml b/.github/workflows/coverage-linux.yml
index c97253621c8dcb..1a8e926dd82129 100644
--- a/.github/workflows/coverage-linux.yml
+++ b/.github/workflows/coverage-linux.yml
@@ -50,13 +50,13 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up sccache
uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5
with:
- version: v0.8.0
+ version: v0.8.1
- name: Environment Information
run: npx envinfo
- name: Install gcovr
diff --git a/.github/workflows/coverage-windows.yml b/.github/workflows/coverage-windows.yml
index 67e503895b25c3..b234e8554ee7c4 100644
--- a/.github/workflows/coverage-windows.yml
+++ b/.github/workflows/coverage-windows.yml
@@ -47,7 +47,7 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install deps
diff --git a/.github/workflows/daily-wpt-fyi.yml b/.github/workflows/daily-wpt-fyi.yml
index 54c2ead0ae787b..d68b27aee57307 100644
--- a/.github/workflows/daily-wpt-fyi.yml
+++ b/.github/workflows/daily-wpt-fyi.yml
@@ -33,7 +33,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Environment Information
@@ -121,7 +121,7 @@ jobs:
run: cp wptreport.json wptreport-${{ steps.setup-node.outputs.node-version }}.json
- name: Upload GitHub Actions artifact
if: ${{ env.WPT_REPORT != '' }}
- uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
+ uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
path: out/wpt/wptreport-*.json
name: WPT Report for ${{ steps.setup-node.outputs.node-version }}
diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml
index d5b24bc2fcf1e3..16844a46def95f 100644
--- a/.github/workflows/doc.yml
+++ b/.github/workflows/doc.yml
@@ -35,7 +35,7 @@ jobs:
run: npx envinfo
- name: Build
run: NODE=$(command -v node) make doc-only
- - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
+ - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: docs
path: out/doc
diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml
index 566f393787b5d8..3d31ea9a17712f 100644
--- a/.github/workflows/linters.yml
+++ b/.github/workflows/linters.yml
@@ -44,7 +44,7 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Environment Information
@@ -64,7 +64,7 @@ jobs:
with:
node-version: ${{ env.NODE_VERSION }}
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Environment Information
@@ -122,7 +122,7 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Environment Information
@@ -139,7 +139,7 @@ jobs:
with:
persist-credentials: false
- name: Use Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Environment Information
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index 26b3c6b9c900e6..866b3e36caccc9 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -33,7 +33,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0d381219ddf674d61a7572ddd19d7941e271515c # v2.9.0
+ uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
@@ -65,7 +65,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: Upload artifact
- uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
+ uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: SARIF file
path: results.sarif
@@ -73,6 +73,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: Upload to code-scanning
- uses: github/codeql-action/upload-sarif@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
+ uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
with:
sarif_file: results.sarif
diff --git a/.github/workflows/test-asan.yml b/.github/workflows/test-asan.yml
index cd0416658fff0c..64317d335c81cf 100644
--- a/.github/workflows/test-asan.yml
+++ b/.github/workflows/test-asan.yml
@@ -51,13 +51,13 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up sccache
uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5
with:
- version: v0.8.0
+ version: v0.8.1
- name: Environment Information
run: npx envinfo
- name: Build
diff --git a/.github/workflows/test-internet.yml b/.github/workflows/test-internet.yml
index 002e6dda71b679..9d8458cbc3bc70 100644
--- a/.github/workflows/test-internet.yml
+++ b/.github/workflows/test-internet.yml
@@ -48,7 +48,7 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Environment Information
diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml
index 8789322522ce43..9d1cb796007710 100644
--- a/.github/workflows/test-linux.yml
+++ b/.github/workflows/test-linux.yml
@@ -41,13 +41,13 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up sccache
uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5
with:
- version: v0.8.0
+ version: v0.8.1
- name: Environment Information
run: npx envinfo
- name: Build
diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml
index c64676978d11fa..ecbd3184a1c145 100644
--- a/.github/workflows/test-macos.yml
+++ b/.github/workflows/test-macos.yml
@@ -48,13 +48,13 @@ jobs:
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up sccache
uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5
with:
- version: v0.8.0
+ version: v0.8.1
- name: Environment Information
run: npx envinfo
# The `npm ci` for this step fails a lot as part of the Test step. Run it
diff --git a/.github/workflows/test-ubsan.yml b/.github/workflows/test-ubsan.yml
index 12ca68c064b912..f62f0a39072b95 100644
--- a/.github/workflows/test-ubsan.yml
+++ b/.github/workflows/test-ubsan.yml
@@ -52,13 +52,13 @@ jobs:
run: |
echo "UBSAN_OPTIONS=suppressions=$GITHUB_WORKSPACE/suppressions.supp" >> $GITHUB_ENV
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up sccache
uses: mozilla-actions/sccache-action@89e9040de88b577a072e3760aaf59f585da083af # v0.0.5
with:
- version: v0.8.0
+ version: v0.8.1
- name: Environment Information
run: npx envinfo
- name: Build
diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml
index 79fb0c3324f7b8..4e9d6660db6c1e 100644
--- a/.github/workflows/tools.yml
+++ b/.github/workflows/tools.yml
@@ -330,7 +330,7 @@ jobs:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
if: matrix.id == 'icu' && (github.event_name == 'schedule' || inputs.id == 'all' || inputs.id == matrix.id)
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
+ uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- run: ${{ matrix.run }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe3f88074b4205..1dea2d6885ac6e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -38,7 +38,8 @@ release.
-22.7.0
+22.8.0
+22.7.0
22.6.0
22.5.1
22.5.0
diff --git a/SECURITY.md b/SECURITY.md
index eac71b4e45e9e0..fc95e1941698e6 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -222,6 +222,6 @@ Security notifications will be distributed via the following methods.
## Comments on this policy
-If you have suggestions on how this process could be improved please submit a
-[pull request](https://github.com/nodejs/nodejs.org) or
-[file an issue](https://github.com/nodejs/security-wg/issues/new) to discuss.
+If you have suggestions on how this process could be improved, please visit
+the [nodejs/security-wg](https://github.com/nodejs/security-wg)
+repository.
diff --git a/benchmark/README.md b/benchmark/README.md
index 96bd0318465f45..2f52a44f251af7 100644
--- a/benchmark/README.md
+++ b/benchmark/README.md
@@ -40,6 +40,7 @@ directories.
* `_cli.R`: parses the command line arguments passed to `compare.R`
* `_http-benchmarkers.js`: selects and runs external tools for benchmarking
the `http` subsystem.
+* `bar.R`: R script for visualizing the output of benchmarks with bar plots.
* `common.js`: see [Common API](#common-api).
* `compare.js`: command line tool for comparing performance between different
Node.js binaries.
diff --git a/benchmark/common.js b/benchmark/common.js
index efe21e871571fc..b4978e8e140b18 100644
--- a/benchmark/common.js
+++ b/benchmark/common.js
@@ -22,27 +22,36 @@ class Benchmark {
this.name = require.main.filename.slice(__dirname.length + 1);
// Execution arguments i.e. flags used to run the jobs
- this.flags = process.env.NODE_BENCHMARK_FLAGS ?
- process.env.NODE_BENCHMARK_FLAGS.split(/\s+/) :
- [];
+ this.flags = process.env.NODE_BENCHMARK_FLAGS?.split(/\s+/) ?? [];
// Parse job-specific configuration from the command line arguments
const argv = process.argv.slice(2);
const parsed_args = this._parseArgs(argv, configs, options);
+
this.options = parsed_args.cli;
this.extra_options = parsed_args.extra;
+ this.combinationFilter = typeof options.combinationFilter === 'function' ? options.combinationFilter : allow;
+
+ if (options.byGroups) {
+ this.queue = [];
+ const groupNames = process.env.NODE_RUN_BENCHMARK_GROUPS?.split(',') ?? Object.keys(configs);
+
+ for (const groupName of groupNames) {
+ const config = { ...configs[groupName][0], group: groupName };
+ const parsed_args = this._parseArgs(argv, config, options);
+
+ this.options = parsed_args.cli;
+ this.extra_options = parsed_args.extra;
+ this.queue = this.queue.concat(this._queue(this.options));
+ }
+ } else {
+ this.queue = this._queue(this.options);
+ }
+
if (options.flags) {
this.flags = this.flags.concat(options.flags);
}
- if (typeof options.combinationFilter === 'function')
- this.combinationFilter = options.combinationFilter;
- else
- this.combinationFilter = allow;
-
- // The configuration list as a queue of jobs
- this.queue = this._queue(this.options);
-
if (this.queue.length === 0)
return;
diff --git a/benchmark/cpu.sh b/benchmark/cpu.sh
new file mode 100755
index 00000000000000..9c9dd7fa4ddc58
--- /dev/null
+++ b/benchmark/cpu.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+CPUPATH=/sys/devices/system/cpu
+
+MAXID=$(cat $CPUPATH/present | awk -F- '{print $NF}')
+
+set_governor() {
+ echo "Setting CPU frequency governor to \"$1\""
+ i=0
+ while [ "$i" -le "$MAXID" ]; do
+ echo "$1" > "$CPUPATH/cpu$i/cpufreq/scaling_governor"
+ i=$((i + 1))
+ done
+}
+
+case "$1" in
+ fast | performance)
+ set_governor "performance"
+ ;;
+ *)
+ echo "Usage: $0 fast"
+ exit 1
+ ;;
+esac
diff --git a/benchmark/http/headers.js b/benchmark/http/headers.js
index e995f380cef151..62612d9fda1911 100644
--- a/benchmark/http/headers.js
+++ b/benchmark/http/headers.js
@@ -4,10 +4,22 @@ const common = require('../common.js');
const http = require('http');
const bench = common.createBenchmark(main, {
- n: [10, 600],
- len: [1, 100],
- duration: 5,
-});
+ fewHeaders: {
+ n: [10],
+ len: [1, 5],
+ duration: 5,
+ },
+ mediumHeaders: {
+ n: [50],
+ len: [1, 10],
+ duration: 5,
+ },
+ manyHeaders: {
+ n: [600],
+ len: [1, 100],
+ duration: 5,
+ },
+}, { byGroups: true });
function main({ len, n, duration }) {
const headers = {
@@ -15,10 +27,9 @@ function main({ len, n, duration }) {
'Transfer-Encoding': 'chunked',
};
- // TODO(BridgeAR): Change this benchmark to use grouped arguments when
- // implemented. https://github.com/nodejs/node/issues/26425
- const Is = [ ...Array(Math.max(n / len, 1)).keys() ];
- const Js = [ ...Array(len).keys() ];
+ const Is = [...Array(n / len).keys()];
+ const Js = [...Array(len).keys()];
+
for (const i of Is) {
headers[`foo${i}`] = Js.map(() => `some header value ${i}`);
}
@@ -27,6 +38,7 @@ function main({ len, n, duration }) {
res.writeHead(200, headers);
res.end();
});
+
server.listen(0, () => {
bench.http({
path: '/',
diff --git a/benchmark/util/get-callsite.js b/benchmark/util/get-callsite.js
new file mode 100644
index 00000000000000..9270f841a243d3
--- /dev/null
+++ b/benchmark/util/get-callsite.js
@@ -0,0 +1,65 @@
+'use strict';
+
+const common = require('../common');
+const { getCallSite } = require('node:util');
+const assert = require('node:assert');
+
+const bench = common.createBenchmark(main, {
+ n: [1e6],
+ method: ['ErrorCallSite', 'ErrorCallSiteSerialized', 'CPP'],
+});
+
+function ErrorGetCallSite() {
+ const originalStackFormatter = Error.prepareStackTrace;
+ Error.prepareStackTrace = (_err, stack) => {
+ if (stack && stack.length > 1) {
+ // Remove node:util
+ return stack.slice(1);
+ }
+ return stack;
+ };
+ const err = new Error();
+ // With the V8 Error API, the stack is not formatted until it is accessed
+ err.stack; // eslint-disable-line no-unused-expressions
+ Error.prepareStackTrace = originalStackFormatter;
+ return err.stack;
+}
+
+function ErrorCallSiteSerialized() {
+ const callsite = ErrorGetCallSite();
+ const serialized = [];
+ for (let i = 0; i < callsite.length; ++i) {
+ serialized.push({
+ functionName: callsite[i].getFunctionName(),
+ scriptName: callsite[i].getFileName(),
+ lineNumber: callsite[i].getLineNumber(),
+ column: callsite[i].getColumnNumber(),
+ });
+ }
+ return serialized;
+}
+
+function main({ n, method }) {
+ let fn;
+ switch (method) {
+ case 'ErrorCallSite':
+ fn = ErrorGetCallSite;
+ break;
+ case 'ErrorCallSiteSerialized':
+ fn = ErrorCallSiteSerialized;
+ break;
+ case 'CPP':
+ fn = getCallSite;
+ break;
+ }
+ let lastStack = {};
+
+ bench.start();
+ for (let i = 0; i < n; i++) {
+ const stack = fn();
+ lastStack = stack;
+ }
+ bench.end(n);
+ // Attempt to avoid dead-code elimination
+ assert.ok(lastStack);
+}
diff --git a/doc/api/child_process.md b/doc/api/child_process.md
index b08ba65917aadc..045f34352a92ee 100644
--- a/doc/api/child_process.md
+++ b/doc/api/child_process.md
@@ -10,7 +10,7 @@ The `node:child_process` module provides the ability to spawn subprocesses in
a manner that is similar, but not identical, to popen(3). This capability
is primarily provided by the [`child_process.spawn()`][] function:
-```js
+```cjs
const { spawn } = require('node:child_process');
const ls = spawn('ls', ['-lh', '/usr']);
@@ -27,6 +27,23 @@ ls.on('close', (code) => {
});
```
+```mjs
+import { spawn } from 'node:child_process';
+const ls = spawn('ls', ['-lh', '/usr']);
+
+ls.stdout.on('data', (data) => {
+ console.log(`stdout: ${data}`);
+});
+
+ls.stderr.on('data', (data) => {
+ console.error(`stderr: ${data}`);
+});
+
+ls.on('close', (code) => {
+ console.log(`child process exited with code ${code}`);
+});
+```
+
By default, pipes for `stdin`, `stdout`, and `stderr` are established between
the parent Node.js process and the spawned subprocess. These pipes have
limited (and platform-specific) capacity. If the subprocess writes to
@@ -108,27 +125,30 @@ When running on Windows, `.bat` and `.cmd` files can be invoked using
[`child_process.exec()`][] do). In any case, if the script filename contains
spaces it needs to be quoted.
-```js
-// On Windows Only...
-const { spawn } = require('node:child_process');
-const bat = spawn('cmd.exe', ['/c', 'my.bat']);
-
-bat.stdout.on('data', (data) => {
- console.log(data.toString());
-});
+```cjs
+// OR...
+const { exec, spawn } = require('node:child_process');
-bat.stderr.on('data', (data) => {
- console.error(data.toString());
+exec('my.bat', (err, stdout, stderr) => {
+ if (err) {
+ console.error(err);
+ return;
+ }
+ console.log(stdout);
});
-bat.on('exit', (code) => {
- console.log(`Child exited with code ${code}`);
+// Script with spaces in the filename:
+const bat = spawn('"my script.cmd"', ['a', 'b'], { shell: true });
+// or:
+exec('"my script.cmd" a b', (err, stdout, stderr) => {
+ // ...
});
```
-```js
+```mjs
// OR...
-const { exec, spawn } = require('node:child_process');
+import { exec, spawn } from 'node:child_process';
+
exec('my.bat', (err, stdout, stderr) => {
if (err) {
console.error(err);
@@ -197,7 +217,7 @@ directly by the shell and special characters (vary based on
[shell](https://en.wikipedia.org/wiki/List_of_command-line_interpreters))
need to be dealt with accordingly:
-```js
+```cjs
const { exec } = require('node:child_process');
exec('"/path/to/test file/test.sh" arg1 arg2');
@@ -208,6 +228,17 @@ exec('echo "The \\$HOME variable is $HOME"');
// The $HOME variable is escaped in the first instance, but not in the second.
```
+```mjs
+import { exec } from 'node:child_process';
+
+exec('"/path/to/test file/test.sh" arg1 arg2');
+// Double quotes are used so that the space in the path is not interpreted as
+// a delimiter of multiple arguments.
+
+exec('echo "The \\$HOME variable is $HOME"');
+// The $HOME variable is escaped in the first instance, but not in the second.
+```
+
**Never pass unsanitized user input to this function. Any input containing shell
metacharacters may be used to trigger arbitrary command execution.**
@@ -225,7 +256,7 @@ can be used to specify the character encoding used to decode the stdout and
stderr output. If `encoding` is `'buffer'`, or an unrecognized character
encoding, `Buffer` objects will be passed to the callback instead.
-```js
+```cjs
const { exec } = require('node:child_process');
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
if (error) {
@@ -237,6 +268,18 @@ exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
});
```
+```mjs
+import { exec } from 'node:child_process';
+exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
+ if (error) {
+ console.error(`exec error: ${error}`);
+ return;
+ }
+ console.log(`stdout: ${stdout}`);
+ console.error(`stderr: ${stderr}`);
+});
+```
+
If `timeout` is greater than `0`, the parent will send the signal
identified by the `killSignal` property (the default is `'SIGTERM'`) if the
child runs longer than `timeout` milliseconds.
@@ -251,7 +294,7 @@ case of an error (including any error resulting in an exit code other than 0), a
rejected promise is returned, with the same `error` object given in the
callback, but with two additional properties `stdout` and `stderr`.
-```js
+```cjs
const util = require('node:util');
const exec = util.promisify(require('node:child_process').exec);
@@ -263,11 +306,24 @@ async function lsExample() {
lsExample();
```
+```mjs
+import { promisify } from 'node:util';
+import child_process from 'node:child_process';
+const exec = promisify(child_process.exec);
+
+async function lsExample() {
+ const { stdout, stderr } = await exec('ls');
+ console.log('stdout:', stdout);
+ console.error('stderr:', stderr);
+}
+lsExample();
+```
+
If the `signal` option is enabled, calling `.abort()` on the corresponding
`AbortController` is similar to calling `.kill()` on the child process except
the error passed to the callback will be an `AbortError`:
-```js
+```cjs
const { exec } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
@@ -277,6 +333,16 @@ const child = exec('grep ssh', { signal }, (error) => {
controller.abort();
```
+```mjs
+import { exec } from 'node:child_process';
+const controller = new AbortController();
+const { signal } = controller;
+const child = exec('grep ssh', { signal }, (error) => {
+ console.error(error); // an AbortError
+});
+controller.abort();
+```
+
### `child_process.execFile(file[, args][, options][, callback])`
> Stability: 1.0 - Early development
@@ -1406,6 +1406,9 @@ Follows [ECMAScript module][] resolution rules.
Use [`--require`][] to load a [CommonJS module][].
Modules preloaded with `--require` will run before modules preloaded with `--import`.
+Modules are preloaded into the main thread as well as any worker threads,
+forked processes, or clustered processes.
+
### `--input-type=type`
> Stability: 1 - Experimental
@@ -2249,7 +2255,7 @@ files must meet **both** criteria to be included in the coverage report.
### `--test-coverage-functions=threshold`
> Stability: 1 - Experimental
@@ -2277,7 +2283,7 @@ files must meet **both** criteria to be included in the coverage report.
### `--test-coverage-lines=threshold`
> Stability: 1 - Experimental
@@ -2867,7 +2873,7 @@ When set, colors will not be used in the REPL.
### `NODE_DISABLE_COMPILE_CACHE=1`
> Stability: 1.1 - Active Development
diff --git a/doc/api/module.md b/doc/api/module.md
index 9b98231f02e52c..ad5ce86c5328a1 100644
--- a/doc/api/module.md
+++ b/doc/api/module.md
@@ -67,7 +67,7 @@ const siblingModule = require('./sibling-module');
### `module.constants.compileCacheStatus`
> Stability: 1.1 - Active Development
@@ -120,7 +120,7 @@ The following constants are returned as the `status` field in the object returne
### `module.enableCompileCache([cacheDir])`
> Stability: 1.1 - Active Development
@@ -165,7 +165,7 @@ be inheritend into the child workers. The directory can be obtained either from
@@ -202,7 +202,7 @@ separately if the same base directory is used to persist the cache, so they can
### `module.getCompileCacheDir()`
> Stability: 1.1 - Active Development
diff --git a/doc/api/perf_hooks.md b/doc/api/perf_hooks.md
index 719c6f11ea946b..e8a9022f4f0a39 100644
--- a/doc/api/perf_hooks.md
+++ b/doc/api/perf_hooks.md
@@ -890,7 +890,7 @@ initialized.
### `performanceNodeTiming.uvMetricsInfo`
* Returns: {Object}
diff --git a/doc/api/sqlite.md b/doc/api/sqlite.md
index ac17ecca640d21..e0d102a1c473a4 100644
--- a/doc/api/sqlite.md
+++ b/doc/api/sqlite.md
@@ -198,7 +198,8 @@ added: v22.5.0
* Returns: {string} The source SQL expanded to include parameter values.
This method returns the source SQL of the prepared statement with parameter
-placeholders replaced by values. This method is a wrapper around
+placeholders replaced by the values that were used during the most recent
+execution of this prepared statement. This method is a wrapper around
[`sqlite3_expanded_sql()`][].
### `statement.get([namedParameters][, ...anonymousParameters])`
@@ -308,11 +309,11 @@ exception.
| SQLite | JavaScript |
| --------- | -------------------- |
-| `NULL` | `null` |
-| `INTEGER` | `number` or `BigInt` |
-| `REAL` | `number` |
-| `TEXT` | `string` |
-| `BLOB` | `Uint8Array` |
+| `NULL` | {null} |
+| `INTEGER` | {number} or {bigint} |
+| `REAL` | {number} |
+| `TEXT` | {string} |
+| `BLOB` | {Uint8Array} |
[SQL injection]: https://en.wikipedia.org/wiki/SQL_injection
[`--experimental-sqlite`]: cli.md#--experimental-sqlite
diff --git a/doc/api/test.md b/doc/api/test.md
index a7af114880ea87..19819202d1d2e1 100644
--- a/doc/api/test.md
+++ b/doc/api/test.md
@@ -1246,7 +1246,7 @@ added:
- v18.9.0
- v16.19.0
changes:
- - version: REPLACEME
+ - version: v22.8.0
pr-url: https://github.com/nodejs/node/pull/53927
description: Added the `isolation` option.
- version: v22.6.0
diff --git a/doc/api/util.md b/doc/api/util.md
index ee6a91af5159d4..c0e55621a15756 100644
--- a/doc/api/util.md
+++ b/doc/api/util.md
@@ -364,6 +364,63 @@ util.formatWithOptions({ colors: true }, 'See object %O', { foo: 42 });
// when printed to a terminal.
```
+## `util.getCallSite(frames)`
+
+> Stability: 1.1 - Active development
+
+
+
+* `frames` {number} Number of frames returned in the stacktrace.
+ **Default:** `10`. Allowable range is between 1 and 200.
+* Returns: {Object\[]} An array of stacktrace objects
+ * `functionName` {string} Returns the name of the function associated with this stack frame.
+ * `scriptName` {string} Returns the name of the resource that contains the script for the
+ function for this StackFrame.
+ * `lineNumber` {number} Returns the number, 1-based, of the line for the associate function call.
+ * `column` {number} Returns the 1-based column offset on the line for the associated function call.
+
+Returns an array of stacktrace objects containing the stack of
+the caller function.
+
+```js
+const util = require('node:util');
+
+function exampleFunction() {
+ const callSites = util.getCallSite();
+
+ console.log('Call Sites:');
+ callSites.forEach((callSite, index) => {
+ console.log(`CallSite ${index + 1}:`);
+ console.log(`Function Name: ${callSite.functionName}`);
+ console.log(`Script Name: ${callSite.scriptName}`);
+ console.log(`Line Number: ${callSite.lineNumer}`);
+ console.log(`Column Number: ${callSite.column}`);
+ });
+ // CallSite 1:
+ // Function Name: exampleFunction
+ // Script Name: /home/example.js
+ // Line Number: 5
+ // Column Number: 26
+
+ // CallSite 2:
+ // Function Name: anotherFunction
+ // Script Name: /home/example.js
+ // Line Number: 22
+ // Column Number: 3
+
+ // ...
+}
+
+// A function to simulate another stack layer
+function anotherFunction() {
+ exampleFunction();
+}
+
+anotherFunction();
+```
+
## `util.getSystemErrorName(err)`
|