Skip to content

Commit 4c2a5f1

Browse files
authored
Merge branch 'nodejs:main' into stream-iter-pending-next-hang
2 parents ba1a8f9 + 92f48f4 commit 4c2a5f1

328 files changed

Lines changed: 16680 additions & 4150 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/commit-lint.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ on:
44
pull_request:
55
branches:
66
- main
7-
- v[0-9]+.x-staging
87

98
env:
109
NODE_VERSION: lts/*

.github/workflows/test-internet.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ permissions:
4444

4545
jobs:
4646
test-internet:
47-
if: github.event_name == 'schedule' && github.repository == 'nodejs/node' || github.event.pull_request.draft == false
47+
if: (github.event_name == 'schedule' && github.repository == 'nodejs/node') || (github.event.pull_request && github.event.pull_request.draft == false)
4848
runs-on: ubuntu-24.04-arm
4949
steps:
5050
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

BUILDING.md

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -237,23 +237,11 @@ tarball and/or browse the git repository checked out at the relevant tag.
237237
### Prerequisites
238238

239239
* [A supported version of Python][Python versions] for building and testing.
240-
* A Rust toolchain if [building Node.js with Temporal support](#building-nodejs-with-temporal-support)
241-
is required (enabled by default starting in Node.js 26).
240+
* A Rust toolchain if [building Node.js with Temporal support](#building-nodejs-with-temporal-support).
242241
* Memory: at least 8GB of RAM is typically required when compiling with 4 parallel jobs (e.g: `make -j4`).
243242

244243
### Unix and macOS
245244

246-
Consult the official [Install Rust](https://rust-lang.org/tools/install/)
247-
instructions to install a Rust toolchain, required for Temporal support introduced in Node.js 25.4.0.
248-
Individual packages such as `rust` and `cargo` in some operating system distributions may be considered
249-
as an alternative, for example in CI environments.
250-
Consult with relevant operating system documentation to ensure that packages
251-
meet the minimum version specified in the
252-
[Building Node.js with Temporal support](#building-nodejs-with-temporal-support) section,
253-
as packaged versions may lag behind the `stable` version installed by the official instructions.
254-
Avoid mixing `rustup` together with `rust` and `cargo` package installations, due to
255-
potential version conflicts.
256-
257245
#### Unix prerequisites
258246

259247
* `gcc` and `g++` >= 13.2 or `clang` and `clang++` >= 19.1
@@ -1062,14 +1050,19 @@ enable FIPS support in Node.js.
10621050

10631051
Node.js supports the [Temporal](https://github.com/tc39/proposal-temporal) APIs, when
10641052
linking statically or dynamically with a version of [temporal\_rs](https://github.com/boa-dev/temporal).
1065-
1066-
Temporal support is enabled by default starting in Node.js 26. Building it
1067-
requires a Rust toolchain:
1053+
Building it requires a Rust toolchain:
10681054

10691055
* rustc >= 1.82 (with LLVM >= 19)
10701056
* cargo >= 1.82
10711057

10721058
Refer to [Install Rust](https://rust-lang.org/tools/install/) for instructions.
1059+
Individual packages such as `rust` and `cargo` in some operating system distributions may be considered
1060+
as an alternative, for example in CI environments.
1061+
Consult with relevant operating system documentation to ensure that packages
1062+
meet the minimum version specified above,
1063+
as packaged versions may lag behind the `stable` version installed by the official instructions.
1064+
Avoid mixing `rustup` together with `rust` and `cargo` package installations, due to
1065+
potential version conflicts.
10731066

10741067
If `--v8-enable-temporal-support` and `--v8-disable-temporal-support` are both
10751068
omitted, `configure.py` probes for `cargo` and `rustc`. If either is missing,

configure.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,18 +1965,29 @@ def configure_node(o):
19651965
msvc_dir = target_arch # 'x64' or 'arm64'
19661966

19671967
vc_tools_dir = os.environ.get('VCToolsInstallDir', '')
1968-
if vc_tools_dir:
1969-
clang_profile_lib = os.path.join(vc_tools_dir, 'lib', msvc_dir, lib_name)
1970-
if os.path.isfile(clang_profile_lib):
1971-
o['variables']['clang_profile_lib'] = clang_profile_lib
1972-
else:
1973-
raise Exception(
1974-
f'PGO profile runtime library not found at {clang_profile_lib}. '
1975-
'Ensure the ClangCL toolset is installed.')
1976-
else:
1968+
if not vc_tools_dir:
19771969
raise Exception(
19781970
'VCToolsInstallDir not set. Run from a Visual Studio command prompt.')
19791971

1972+
# Primary location: VS2026 and VS2022 x64
1973+
candidates = [os.path.join(vc_tools_dir, 'lib', msvc_dir, lib_name)]
1974+
1975+
# Secondary location: VS2022 arm64 fallback
1976+
clang_major = options.clang_cl.split('.', 1)[0]
1977+
candidates.append(os.path.normpath(os.path.join(
1978+
vc_tools_dir, '..', '..', 'Llvm', msvc_dir,
1979+
'lib', 'clang', clang_major, 'lib', 'windows', lib_name)))
1980+
1981+
clang_profile_lib = next(
1982+
(p for p in candidates if os.path.isfile(p)), None)
1983+
if clang_profile_lib:
1984+
o['variables']['clang_profile_lib'] = clang_profile_lib
1985+
else:
1986+
raise Exception(
1987+
f'PGO profile runtime library {lib_name} not found. Searched:\n ' +
1988+
'\n '.join(candidates) +
1989+
'\nEnsure the ClangCL toolset is installed.')
1990+
19801991
if flavor != 'win' and options.enable_thin_lto:
19811992
raise Exception(
19821993
'Use --enable-lto instead.')

doc/api/cli.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,6 +1444,16 @@ The flag may be specified more than once; tests must contain **every**
14441444
filter value to run. See [Test tags][] for details on declaring and
14451445
inheriting tags.
14461446

1447+
### `--experimental-vfs`
1448+
1449+
<!-- YAML
1450+
added: REPLACEME
1451+
-->
1452+
1453+
> Stability: 1 - Experimental
1454+
1455+
Enable the experimental [`node:vfs`][] module.
1456+
14471457
### `--experimental-vm-modules`
14481458

14491459
<!-- YAML
@@ -3786,6 +3796,7 @@ one is included in the list below.
37863796
* `--experimental-stream-iter`
37873797
* `--experimental-test-isolation`
37883798
* `--experimental-top-level-await`
3799+
* `--experimental-vfs`
37893800
* `--experimental-vm-modules`
37903801
* `--experimental-wasi-unstable-preview1`
37913802
* `--force-context-aware`
@@ -4428,6 +4439,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
44284439
[`node:ffi`]: ffi.md
44294440
[`node:sqlite`]: sqlite.md
44304441
[`node:stream/iter`]: stream_iter.md
4442+
[`node:vfs`]: vfs.md
44314443
[`process.setUncaughtExceptionCaptureCallback()`]: process.md#processsetuncaughtexceptioncapturecallbackfn
44324444
[`tls.DEFAULT_MAX_VERSION`]: tls.md#tlsdefault_max_version
44334445
[`tls.DEFAULT_MIN_VERSION`]: tls.md#tlsdefault_min_version

doc/api/errors.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3104,7 +3104,7 @@ The context must be a `SecureContext`.
31043104

31053105
### `ERR_TLS_INVALID_PROTOCOL_METHOD`
31063106

3107-
The specified `secureProtocol` method is invalid. It is either unknown, or
3107+
The specified `secureProtocol` method is invalid. It is either unknown, or
31083108
disabled because it is insecure.
31093109

31103110
<a id="ERR_TLS_INVALID_PROTOCOL_VERSION"></a>

doc/api/ffi.md

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -124,18 +124,18 @@ such as `0` and `1`; JavaScript `true` and `false` are not accepted.
124124

125125
Functions and callbacks are described with signature objects.
126126

127-
Supported fields:
127+
Signature objects may contain the following properties, both of which are
128+
optional:
128129

129-
* `result`, `return`, or `returns` for the return type.
130-
* `parameters` or `arguments` for the parameter type list.
130+
* `return` {string} A [type name][type names] specifying the return type of the
131+
function or callback. **Default:** `'void'`.
132+
* `arguments` {string\[]} An array of [type names][] specifying the argument
133+
type list of the function or callback. **Default:** `[]`.
131134

132-
Only one return-type field and one parameter-list field may be present in a
133-
single signature object.
134-
135-
```cjs
135+
```js
136136
const signature = {
137-
result: 'i32',
138-
parameters: ['i32', 'i32'],
137+
return: 'i32',
138+
arguments: ['i32', 'i32'],
139139
};
140140
```
141141

@@ -193,7 +193,7 @@ import { dlopen } from 'node:ffi';
193193

194194
{
195195
using handle = dlopen('./mylib.so', {
196-
add_i32: { parameters: ['i32', 'i32'], result: 'i32' },
196+
add_i32: { arguments: ['i32', 'i32'], return: 'i32' },
197197
});
198198
console.log(handle.functions.add_i32(20, 22));
199199
} // handle.lib.close() is invoked automatically here.
@@ -203,8 +203,8 @@ import { dlopen } from 'node:ffi';
203203
import { dlopen } from 'node:ffi';
204204

205205
const { lib, functions } = dlopen('./mylib.so', {
206-
add_i32: { parameters: ['i32', 'i32'], result: 'i32' },
207-
string_length: { parameters: ['pointer'], result: 'u64' },
206+
add_i32: { arguments: ['i32', 'i32'], return: 'i32' },
207+
string_length: { arguments: ['pointer'], return: 'u64' },
208208
});
209209

210210
console.log(functions.add_i32(20, 22));
@@ -214,8 +214,8 @@ console.log(functions.add_i32(20, 22));
214214
const { dlopen } = require('node:ffi');
215215

216216
const { lib, functions } = dlopen('./mylib.so', {
217-
add_i32: { parameters: ['i32', 'i32'], result: 'i32' },
218-
string_length: { parameters: ['pointer'], result: 'u64' },
217+
add_i32: { arguments: ['i32', 'i32'], return: 'i32' },
218+
string_length: { arguments: ['pointer'], return: 'u64' },
219219
});
220220

221221
console.log(functions.add_i32(20, 22));
@@ -356,8 +356,8 @@ const { DynamicLibrary } = require('node:ffi');
356356

357357
const lib = new DynamicLibrary('./mylib.so');
358358
const add = lib.getFunction('add_i32', {
359-
parameters: ['i32', 'i32'],
360-
result: 'i32',
359+
arguments: ['i32', 'i32'],
360+
return: 'i32',
361361
});
362362

363363
console.log(add(20, 22));
@@ -407,7 +407,7 @@ const { DynamicLibrary } = require('node:ffi');
407407
const lib = new DynamicLibrary('./mylib.so');
408408

409409
const callback = lib.registerCallback(
410-
{ parameters: ['i32'], result: 'i32' },
410+
{ arguments: ['i32'], return: 'i32' },
411411
(value) => value * 2,
412412
);
413413
```
@@ -417,7 +417,7 @@ Callbacks are subject to the following restrictions:
417417
* They must be invoked on the same system thread where they were created.
418418
* They must not throw exceptions.
419419
* They must not return promises.
420-
* They must return a value compatible with the declared result type.
420+
* They must return a value compatible with the declared return type.
421421
* They must not call `library.close()` on their owning library while running.
422422
* They must not unregister themselves while running.
423423

@@ -465,7 +465,7 @@ JavaScript `number` values that match the declared type.
465465

466466
For 64-bit integer types (`i64` and `u64`), pass JavaScript `bigint` values.
467467

468-
For pointer-like parameters:
468+
For pointer-like arguments:
469469

470470
* `null` and `undefined` are passed as null pointers.
471471
* `string` values are copied to temporary NUL-terminated UTF-8 strings for the
@@ -727,3 +727,4 @@ and keep callback and pointer lifetimes explicit on the native side.
727727
[`--allow-ffi`]: cli.md#--allow-ffi
728728
[`ffi.toBuffer(pointer, length, copy)`]: #ffitobufferpointer-length-copy
729729
[`using`]: https://tc39.es/proposal-explicit-resource-management/#sec-using-declarations
730+
[type names]: #type-names

doc/api/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
* [URL](url.md)
6666
* [Utilities](util.md)
6767
* [V8](v8.md)
68+
* [Virtual File System](vfs.md)
6869
* [VM](vm.md)
6970
* [WASI](wasi.md)
7071
* [Web Crypto API](webcrypto.md)

doc/api/modules.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ console.log(distance); // undefined
286286
```
287287

288288
Notice in the example above, when the `module.exports` export name is used, named exports
289-
will be lost to CommonJS consumers. To allow CommonJS consumers to continue accessing
289+
will be lost to CommonJS consumers. To allow CommonJS consumers to continue accessing
290290
named exports, the module can make sure that the default export is an object with the
291291
named exports attached to it as properties. For example with the example above,
292292
`distance` can be attached to the default export, the `Point` class, as a static method.
@@ -359,8 +359,7 @@ require(X) from module at path Y
359359
MAYBE_DETECT_AND_LOAD(X)
360360
1. If X parses as a CommonJS module, load X as a CommonJS module. STOP.
361361
2. Else, if the source code of X can be parsed as ECMAScript module using
362-
<a href="esm.md#resolver-algorithm-specification">DETECT_MODULE_SYNTAX defined in
363-
the ESM resolver</a>,
362+
DETECT_MODULE_SYNTAX defined in the ESM resolver,
364363
a. Load X as an ECMAScript module. STOP.
365364
3. THROW the SyntaxError from attempting to parse X as CommonJS in 1. STOP.
366365
@@ -424,7 +423,7 @@ LOAD_PACKAGE_IMPORTS(X, DIR)
424423
a. let CONDITIONS = ["node", "require", "module-sync"]
425424
b. Else, let CONDITIONS = ["node", "require"]
426425
5. let MATCH = PACKAGE_IMPORTS_RESOLVE(X, pathToFileURL(SCOPE),
427-
CONDITIONS) <a href="esm.md#resolver-algorithm-specification">defined in the ESM resolver</a>.
426+
CONDITIONS) defined in the ESM resolver.
428427
6. RESOLVE_ESM_MATCH(MATCH).
429428
430429
LOAD_PACKAGE_EXPORTS(X, DIR)
@@ -438,7 +437,7 @@ LOAD_PACKAGE_EXPORTS(X, DIR)
438437
a. let CONDITIONS = ["node", "require", "module-sync"]
439438
b. Else, let CONDITIONS = ["node", "require"]
440439
6. let MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(DIR/NAME), "." + SUBPATH,
441-
`package.json` "exports", CONDITIONS) <a href="esm.md#resolver-algorithm-specification">defined in the ESM resolver</a>.
440+
`package.json` "exports", CONDITIONS) defined in the ESM resolver.
442441
7. RESOLVE_ESM_MATCH(MATCH)
443442
444443
LOAD_PACKAGE_SELF(X, DIR)
@@ -448,7 +447,7 @@ LOAD_PACKAGE_SELF(X, DIR)
448447
4. If the SCOPE/package.json "name" is not the first segment of X, return.
449448
5. let MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(SCOPE),
450449
"." + X.slice("name".length), `package.json` "exports", ["node", "require"])
451-
<a href="esm.md#resolver-algorithm-specification">defined in the ESM resolver</a>.
450+
defined in the ESM resolver.
452451
6. RESOLVE_ESM_MATCH(MATCH)
453452
454453
RESOLVE_ESM_MATCH(MATCH)
@@ -458,6 +457,8 @@ RESOLVE_ESM_MATCH(MATCH)
458457
3. THROW "not found"
459458
```
460459

460+
The "ESM resolver" is defined [in the ESM documentation](esm.md#resolver-algorithm-specification).
461+
461462
## Caching
462463

463464
<!--type=misc-->

doc/api/permissions.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ flag. For WASI, use the [`--allow-wasi`][] flag. For FFI, use the
7878

7979
When enabling the Permission Model through the [`--permission`][]
8080
flag a new property `permission` is added to the `process` object.
81-
This property contains one function:
81+
This property contains the following functions:
8282

8383
##### `permission.has(scope[, reference])`
8484

@@ -92,6 +92,41 @@ process.permission.has('fs.read'); // true
9292
process.permission.has('fs.read', '/home/rafaelgss/protected-folder'); // false
9393
```
9494

95+
##### `permission.drop(scope[, reference])`
96+
97+
API call to drop permissions at runtime. This operation is **irreversible**.
98+
99+
When called without a reference, the entire scope is dropped. When called
100+
with a reference, only the permission for that specific resource is revoked.
101+
Dropping a permission only affects future access checks. It does not close or
102+
revoke access to resources that are already open, such as file descriptors,
103+
network sockets, child processes, or worker threads. Applications are
104+
responsible for closing or terminating those resources when they are no longer
105+
needed.
106+
107+
You can only drop the exact resource that was explicitly granted. The
108+
reference passed to `drop()` must match the original grant. If a permission
109+
was granted using a wildcard (`*`), only the entire scope can be dropped
110+
(by calling `drop()` without a reference). If a directory was granted
111+
(e.g. `--allow-fs-read=/my/folder`), you cannot drop individual files
112+
inside it - you must drop the same directory that was originally granted.
113+
114+
```js
115+
const fs = require('node:fs');
116+
117+
// Read config at startup while we still have permission
118+
const config = fs.readFileSync('/etc/myapp/config.json', 'utf8');
119+
120+
// Drop read access to /etc/myapp after initialization
121+
process.permission.drop('fs.read', '/etc/myapp');
122+
123+
// This will now throw ERR_ACCESS_DENIED
124+
process.permission.has('fs.read', '/etc/myapp/config.json'); // false
125+
126+
// Drop child process permission entirely
127+
process.permission.drop('child');
128+
```
129+
95130
#### File System Permissions
96131

97132
The Permission Model, by default, restricts access to the file system through the `node:fs` module.

0 commit comments

Comments
 (0)