Skip to content

Commit 49ad950

Browse files
authored
vfs: unflag
Enable node:vfs by default. --no-experimental-vfs disables node:vfs exposure and --vfs-load. Assisted-by: pi Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: #66318 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Paolo Insogna <paolo@cowtech.it>
1 parent f0f8115 commit 49ad950

134 files changed

Lines changed: 247 additions & 227 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.

‎doc/api/cli.md‎

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ so mounting one is gated on its own flag rather than on `--allow-fs-read` or
330330
`--allow-fs-write`.
331331

332332
```console
333-
$ node --experimental-vfs --permission --allow-fs-vfs app.js
333+
$ node --permission --allow-fs-vfs app.js
334334
```
335335

336336
### `--allow-fs-write`
@@ -1711,16 +1711,6 @@ with AND, so a test must satisfy every expression to run.
17111711
A malformed expression causes the test runner to exit with a non-zero status
17121712
before running any tests.
17131713

1714-
### `--experimental-vfs`
1715-
1716-
<!-- YAML
1717-
added: v26.4.0
1718-
-->
1719-
1720-
> Stability: 1 - Experimental
1721-
1722-
Enable the experimental [`node:vfs`][] module.
1723-
17241714
### `--experimental-vm-modules`
17251715

17261716
<!-- YAML
@@ -2364,6 +2354,18 @@ changes:
23642354

23652355
Disable the experimental [`node:sqlite`][] module.
23662356

2357+
### `--no-experimental-vfs`
2358+
2359+
<!-- YAML
2360+
added: v26.4.0
2361+
changes:
2362+
- version: REPLACEME
2363+
pr-url: https://github.com/nodejs/node/pull/66318
2364+
description: VFS is unflagged but still experimental.
2365+
-->
2366+
2367+
Disable the experimental [`node:vfs`][] module and `--vfs-load`.
2368+
23672369
### `--no-experimental-webstorage`
23682370

23692371
<!-- YAML
@@ -3907,11 +3909,13 @@ added: v26.10.0
39073909

39083910
* `source` {string} A directory or an archive file to mount and run.
39093911

3910-
Requires [`--experimental-vfs`][]. May be given at most once.
3912+
May be given at most once.
39113913

39123914
Mounts `source` as a virtual file system ([`node:vfs`][]), and runs the entry
39133915
point and all subsequent `require()`/`import` resolution against that mount
3914-
rather than the real file system. The mount is placed at a reserved mount point
3916+
rather than the real file system. This option is unavailable when
3917+
`--no-experimental-vfs` disables [`node:vfs`][]. The mount is placed at a
3918+
reserved mount point
39153919
assigned by Node.js, so it never shadows real paths and no target can be
39163920
chosen. The entry point is taken from the mount the same way `node <directory>`
39173921
takes one: the mount's own `package.json` `"main"`, or `index.js`. Any
@@ -3942,18 +3946,17 @@ same thing in all of them.
39423946

39433947
A worker created with its own `execArgv` inherits none of the parent's options,
39443948
and so does not mount the source at all. To run a script from the mount, such a
3945-
worker must be given the same options again, `--experimental-vfs` and
3946-
`--vfs-load`; without them, that thread has no mount for the script to come
3947-
from, and the worker fails to load it. `--experimental-vfs` is also what makes
3948-
[`node:vfs`][] available to the worker's own code. A worker whose script comes
3949-
from anywhere else, such as the real file system, needs nothing added.
3949+
worker must be given `--vfs-load` again; without it, that thread has no mount
3950+
for the script to come from, and the worker fails to load it. [`node:vfs`][] is
3951+
available to worker code without an experimental flag. A worker whose script
3952+
comes from anywhere else, such as the real file system, needs nothing added.
39503953

39513954
`--vfs-load` is not permitted in [`NODE_OPTIONS`][]: which entry point runs is
39523955
the command line's decision, and the environment must not be able to redirect
39533956
it.
39543957

39553958
```console
3956-
$ node --experimental-vfs --vfs-load=app.zip
3959+
$ node --vfs-load=app.zip
39573960
```
39583961

39593962
### `--watch`
@@ -4280,7 +4283,6 @@ one is included in the list below.
42804283
* `--experimental-stream-iter`
42814284
* `--experimental-test-isolation`
42824285
* `--experimental-top-level-await`
4283-
* `--experimental-vfs`
42844286
* `--experimental-vm-modules`
42854287
* `--experimental-wasi-unstable-preview1`
42864288
* `--experimental-web-worker`
@@ -4315,6 +4317,7 @@ one is included in the list below.
43154317
* `--no-experimental-global-navigator`
43164318
* `--no-experimental-sqlite`
43174319
* `--no-experimental-strip-types`
4320+
* `--no-experimental-vfs`
43184321
* `--no-experimental-webstorage`
43194322
* `--no-extra-info-on-fatal-exception`
43204323
* `--no-force-async-hooks-checks`
@@ -4914,7 +4917,6 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
49144917
[`--env-file-if-exists`]: #--env-file-if-existsfile
49154918
[`--env-file`]: #--env-filefile
49164919
[`--experimental-sea-config`]: single-executable-applications.md#1-generating-single-executable-preparation-blobs
4917-
[`--experimental-vfs`]: #--experimental-vfs
49184920
[`--heap-prof-dir`]: #--heap-prof-dir
49194921
[`--import`]: #--importmodule
49204922
[`--no-require-module`]: #--no-require-module

‎doc/api/vfs.md‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import vfs from 'node:vfs';
2424
const vfs = require('node:vfs');
2525
```
2626

27-
This module is only available under the `node:` scheme, and only when Node.js
28-
is started with the `--experimental-vfs` flag.
27+
This module is only available under the `node:` scheme. Loading it emits an
28+
`ExperimentalWarning`.
2929

3030
## Security
3131

@@ -77,8 +77,9 @@ added: v26.4.0
7777
* `provider` {VirtualProvider} The provider to use. **Default:**
7878
`new MemoryProvider()`.
7979
* `options` {Object}
80-
* `emitExperimentalWarning` {boolean} Whether to emit the experimental
81-
warning when the instance is created. **Default:** `true`.
80+
* `emitExperimentalWarning` {boolean} Whether to emit an experimental warning
81+
when an instance is created. **Default:** `true`. Loading `node:vfs` emits
82+
the warning regardless of this option.
8283
* Returns: {VirtualFileSystem}
8384

8485
Convenience factory equivalent to `new VirtualFileSystem(provider, options)`.
@@ -148,7 +149,7 @@ vfs.registerProvider({
148149
```
149150

150151
```console
151-
$ node --experimental-vfs --require ./provider.js \
152+
$ node --require ./provider.js \
152153
--vfs-load archive.customfmt
153154
```
154155

@@ -193,8 +194,9 @@ added: v26.4.0
193194
* `provider` {VirtualProvider} The provider to use. **Default:**
194195
`new MemoryProvider()`.
195196
* `options` {Object}
196-
* `emitExperimentalWarning` {boolean} Whether to emit the experimental
197-
warning. **Default:** `true`.
197+
* `emitExperimentalWarning` {boolean} Whether to emit an experimental warning
198+
when an instance is created. **Default:** `true`. Loading `node:vfs` emits
199+
the warning regardless of this option.
198200

199201
### `vfs.mount()`
200202

‎doc/node.1‎

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ A mounted VFS serves paths that the file system permissions do not describe,
210210
so mounting one is gated on its own flag rather than on \fB--allow-fs-read\fR or
211211
\fB--allow-fs-write\fR.
212212
.Bd -literal
213-
$ node --experimental-vfs --permission --allow-fs-vfs app.js
213+
$ node --permission --allow-fs-vfs app.js
214214
.Ed
215215
.
216216
.It Fl -allow-fs-write
@@ -930,9 +930,6 @@ with AND, so a test must satisfy every expression to run.
930930
A malformed expression causes the test runner to exit with a non-zero status
931931
before running any tests.
932932
.
933-
.It Fl -experimental-vfs
934-
Enable the experimental \fBnode:vfs\fR module.
935-
.
936933
.It Fl -experimental-vm-modules
937934
Enable experimental ES Module support in the \fBnode:vm\fR module.
938935
.
@@ -1233,6 +1230,9 @@ Legacy alias for \fB--no-require-module\fR.
12331230
.It Fl -no-experimental-sqlite
12341231
Disable the experimental \fBnode:sqlite\fR module.
12351232
.
1233+
.It Fl -no-experimental-vfs
1234+
Disable the experimental \fBnode:vfs\fR module and \fB--vfs-load\fR.
1235+
.
12361236
.It Fl -no-experimental-webstorage
12371237
Disable \fBWeb Storage\fR support.
12381238
.
@@ -1973,10 +1973,12 @@ Print node's version.
19731973
.It
19741974
\fBsource\fR \fB{string}\fR A directory or an archive file to mount and run.
19751975
.El
1976-
Requires \fB--experimental-vfs\fR. May be given at most once.
1976+
May be given at most once.
19771977
Mounts \fBsource\fR as a virtual file system (\fBnode:vfs\fR), and runs the entry
19781978
point and all subsequent \fBrequire()\fR/\fBimport\fR resolution against that mount
1979-
rather than the real file system. The mount is placed at a reserved mount point
1979+
rather than the real file system. This option is unavailable when
1980+
\fB--no-experimental-vfs\fR disables \fBnode:vfs\fR. The mount is placed at a
1981+
reserved mount point
19801982
assigned by Node.js, so it never shadows real paths and no target can be
19811983
chosen. The entry point is taken from the mount the same way \fBnode <directory>\fR
19821984
takes one: the mount's own \fBpackage.json\fR \fB"main"\fR, or \fBindex.js\fR. Any
@@ -2004,16 +2006,15 @@ mounts it, whatever else that thread mounts, so a path into the mount means the
20042006
same thing in all of them.
20052007
A worker created with its own \fBexecArgv\fR inherits none of the parent's options,
20062008
and so does not mount the source at all. To run a script from the mount, such a
2007-
worker must be given the same options again, \fB--experimental-vfs\fR and
2008-
\fB--vfs-load\fR; without them, that thread has no mount for the script to come
2009-
from, and the worker fails to load it. \fB--experimental-vfs\fR is also what makes
2010-
\fBnode:vfs\fR available to the worker's own code. A worker whose script comes
2011-
from anywhere else, such as the real file system, needs nothing added.
2009+
worker must be given \fB--vfs-load\fR again; without it, that thread has no mount
2010+
for the script to come from, and the worker fails to load it. \fBnode:vfs\fR is
2011+
available to worker code without an experimental flag. A worker whose script
2012+
comes from anywhere else, such as the real file system, needs nothing added.
20122013
\fB--vfs-load\fR is not permitted in \fBNODE_OPTIONS\fR: which entry point runs is
20132014
the command line's decision, and the environment must not be able to redirect
20142015
it.
20152016
.Bd -literal
2016-
$ node --experimental-vfs --vfs-load=app.zip
2017+
$ node --vfs-load=app.zip
20172018
.Ed
20182019
.
20192020
.It Fl -watch
@@ -2271,8 +2272,6 @@ one is included in the list below.
22712272
.It
22722273
\fB--experimental-top-level-await\fR
22732274
.It
2274-
\fB--experimental-vfs\fR
2275-
.It
22762275
\fB--experimental-vm-modules\fR
22772276
.It
22782277
\fB--experimental-wasi-unstable-preview1\fR
@@ -2341,6 +2340,8 @@ one is included in the list below.
23412340
.It
23422341
\fB--no-experimental-strip-types\fR
23432342
.It
2343+
\fB--no-experimental-vfs\fR
2344+
.It
23442345
\fB--no-experimental-webstorage\fR
23452346
.It
23462347
\fB--no-extra-info-on-fatal-exception\fR

‎lib/internal/vfs/file_system.js‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ const {
1515
ERR_INVALID_STATE,
1616
},
1717
} = require('internal/errors');
18-
const { validateBoolean } = require('internal/validators');
1918
const { MemoryProvider } = require('internal/vfs/providers/memory');
2019
const path = require('path');
2120
const { posix: pathPosix, resolve: resolvePath, sep, toNamespacedPath } = path;
@@ -39,6 +38,7 @@ const {
3938
const { VirtualReadStream, VirtualWriteStream } = require('internal/vfs/streams');
4039
const { VirtualDir } = require('internal/vfs/dir');
4140
const { emitExperimentalWarning, kEmptyObject } = require('internal/util');
41+
const { validateBoolean } = require('internal/validators');
4242
let debug = require('internal/util/debuglog').debuglog('vfs', (fn) => {
4343
debug = fn;
4444
});
@@ -111,7 +111,6 @@ class VirtualFileSystem {
111111
/**
112112
* @param {VirtualProvider|object} [providerOrOptions] The provider to use, or options
113113
* @param {object} [options] Configuration options
114-
* @param {boolean} [options.emitExperimentalWarning] Emit the experimental warning (default: true)
115114
*/
116115
constructor(providerOrOptions, options = kEmptyObject) {
117116
let provider = null;

‎lib/vfs.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ const {
44
FunctionPrototypeSymbolHasInstance,
55
} = primordials;
66

7+
const { emitExperimentalWarning } = require('internal/util');
8+
emitExperimentalWarning('VirtualFileSystem');
9+
710
const { VirtualFileSystem } = require('internal/vfs/file_system');
811
const { VirtualProvider } = require('internal/vfs/provider');
912
const { MemoryProvider } = require('internal/vfs/providers/memory');

‎src/node.cc‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,7 @@ static ExitCode InitializeNodeWithArgsInternal(
11191119
{
11201120
auto* env_options = per_process::cli_options->per_isolate->per_env.get();
11211121
if (!env_options->experimental_vfs && env_options->vfs_load) {
1122-
errors->push_back("--vfs-load requires --experimental-vfs");
1122+
errors->push_back("--vfs-load requires node:vfs to be enabled");
11231123
}
11241124
// A second --vfs-load would silently replace the first, and the option
11251125
// itself cannot say how often it was given; count it in the node options

‎src/node_options.cc‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,8 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
801801
AddOption("--experimental-vfs",
802802
"experimental node:vfs module",
803803
BOOL_FIELD(experimental_vfs),
804-
kAllowedInEnvvar);
804+
kAllowedInEnvvar,
805+
true);
805806
// Choosing the entry point is the command line's alone: an environment
806807
// variable must not be able to redirect what a `node <args>` invocation runs,
807808
// so this is rejected in NODE_OPTIONS. The source and whether to run from it
@@ -810,7 +811,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
810811
AddOption("--vfs-load",
811812
"mount a directory or archive as a virtual file system and run the "
812813
"entry point and module resolution against it instead of the real "
813-
"file system (may be given once; requires --experimental-vfs)",
814+
"file system (may be given once)",
814815
&EnvironmentOptions::vfs_load_source,
815816
kDisallowedInEnvvar);
816817
AddOption("[vfs_load_set]", "", BOOL_FIELD(vfs_load));

‎src/node_options.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ class EnvironmentOptions : public Options {
215215
DEFINE_BOOL_FIELD(experimental_websocket) = true;
216216
DEFINE_BOOL_FIELD(experimental_sqlite) = HAVE_SQLITE;
217217
DEFINE_BOOL_FIELD(experimental_stream_iter) = EXPERIMENTALS_DEFAULT_VALUE;
218-
DEFINE_BOOL_FIELD(experimental_vfs) = EXPERIMENTALS_DEFAULT_VALUE;
218+
DEFINE_BOOL_FIELD(experimental_vfs) = true;
219219
DEFINE_BOOL_FIELD(vfs_load) = false;
220220
DEFINE_BOOL_FIELD(webstorage) = HAVE_SQLITE;
221221
DEFINE_BOOL_FIELD(experimental_dtls) = EXPERIMENTALS_DEFAULT_VALUE;

‎test/ffi/test-ffi-vfs.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Flags: --experimental-vfs
1+
// Flags: --disable-warning=ExperimentalWarning
22
'use strict';
33
const common = require('../common');
44
common.skipIfFFIMissing();

‎test/parallel/test-module-builtin-experimental.js‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Flags: --disable-warning=ExperimentalWarning
12
'use strict';
23

34
const common = require('../common');
@@ -8,7 +9,6 @@ const experimentalBuiltins = [
89
['bench/reporters', '--experimental-bench', true],
910
['dtls', '--experimental-dtls', common.hasDtls],
1011
['quic', '--experimental-quic', common.hasQuic],
11-
['vfs', '--experimental-vfs', true],
1212
].filter(([, , available]) => available);
1313

1414
for (const [id, flag] of experimentalBuiltins) {
@@ -51,7 +51,14 @@ if (common.hasFFI) {
5151
], { status: 0 });
5252
}
5353

54-
const schemeOnlyBuiltins = ['node:test', 'node:sea'];
54+
// node:vfs is enabled by default and can be disabled with
55+
// --no-experimental-vfs.
56+
spawnSyncAndAssert(process.execPath, [
57+
'--no-experimental-vfs',
58+
'-e', `const m = require('node:module'); if (m.builtinModules.includes('node:vfs')) process.exit(1); try { require('node:vfs'); } catch (e) { if (e.code === 'ERR_UNKNOWN_BUILTIN_MODULE') process.exit(0); } process.exit(1);`,
59+
], { status: 0 });
60+
61+
const schemeOnlyBuiltins = ['node:test', 'node:sea', 'node:vfs'];
5562
if (common.hasFFI) {
5663
schemeOnlyBuiltins.push('node:ffi');
5764
}

0 commit comments

Comments
 (0)