Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
33a42d4
fs: add virtual file system support
mcollina Jan 22, 2026
2f6d457
vfs: add Windows path compatibility
mcollina Jan 23, 2026
183be2f
sea: support VFS in embedderRequire
mcollina Jan 23, 2026
8a728ee
test: add tmpdir.refresh() to SEA VFS test
mcollina Jan 24, 2026
175faf4
test: update SEA VFS test for new buildSEA API
mcollina Jan 25, 2026
7b43547
vfs: add provider-based architecture and node:vfs module
mcollina Jan 27, 2026
7fecdcf
vfs: remove backward compat methods, use standard fs API
mcollina Jan 27, 2026
ed6939b
vfs: address review comments
mcollina Jan 27, 2026
583dad5
vfs: fix lint errors
mcollina Jan 28, 2026
6a2caa4
vfs: fix lint errors
mcollina Jan 28, 2026
d1671b4
vfs: remove public createSEA()
mcollina Jan 28, 2026
807270a
vfs: address review comments
mcollina Jan 28, 2026
fa272f7
doc: address review comments on VFS documentation
mcollina Jan 28, 2026
0a5046e
doc: clarify virtualCwd behavior in Worker threads
mcollina Jan 28, 2026
5b728bd
vfs: add RealFSProvider for mounting real directories
mcollina Jan 28, 2026
6fbf2e4
tools: add VFS types to doc type-parser
mcollina Jan 28, 2026
4cc76db
doc: use REPLACEME for version placeholders in vfs.md
mcollina Jan 29, 2026
d6fd085
doc: add security warnings and symlink documentation to vfs.md
mcollina Jan 29, 2026
1378599
vfs: address code review feedback from @jasnell
mcollina Jan 29, 2026
4168c1b
vfs: add overlay mode for selective file interception
mcollina Jan 29, 2026
7a07728
vfs: add tests and fix appendFile, add readonly checks
mcollina Jan 30, 2026
96279a2
fs: remove createVirtual, use node:vfs instead
mcollina Jan 31, 2026
372350d
vfs: add watch and watchFile support
mcollina Jan 31, 2026
102ffc5
vfs: improve test coverage for watch implementation
mcollina Jan 31, 2026
df91d30
vfs: remove unused utility functions from module_hooks
mcollina Jan 31, 2026
b32c4c2
vfs: add test for symlink target creation after symlink
mcollina Feb 1, 2026
8a37803
doc: add worker thread limitations to VFS documentation
mcollina Feb 1, 2026
1069a53
doc: clarify VFS accepts same types as fs module
mcollina Feb 1, 2026
d52d9bc
vfs: remove unused entries.js, add error tests
mcollina Feb 1, 2026
2dc1129
vfs: remove unused exports from fd.js and stats.js
mcollina Feb 1, 2026
9723628
vfs: remove unused VirtualFD methods
mcollina Feb 1, 2026
d84f7e4
vfs: remove more unused VirtualFD code
mcollina Feb 1, 2026
b7d0d6a
vfs: address Aviv's review comments
mcollina Feb 2, 2026
340fbf6
test: improve VFS code coverage
mcollina Feb 2, 2026
272b6b3
Update lib/internal/vfs/module_hooks.js
mcollina Feb 2, 2026
e91ecb5
Update lib/internal/vfs/module_hooks.js
mcollina Feb 2, 2026
10ba54d
vfs: address aduh95 review comments
mcollina Feb 2, 2026
b6cf9b4
vfs: remove SEAProvider export and hasSeaAssets
mcollina Feb 3, 2026
b191bd9
vfs: remove addFile and addDirectory methods
mcollina Feb 3, 2026
2855a7c
doc: alphabetize VirtualFileSystem members in vfs.md
mcollina Feb 3, 2026
db5cbb3
Update single-executable-applications.md
mcollina Feb 3, 2026
67fa9c8
sea: remove getVfs from public API
mcollina Feb 3, 2026
9e7f6cd
doc: explain symlink behavior in overlay mode
mcollina Feb 3, 2026
48de1d0
doc: document overlay mode behavior for fs operations
mcollina Feb 3, 2026
1a5c13a
vfs: add Symbol.dispose support for automatic unmount
mcollina Feb 3, 2026
96736f6
vfs: add missing JSDoc @returns for mount()
mcollina Feb 3, 2026
8c0a3e1
vfs: only initialize SEA VFS when assets exist
mcollina Feb 3, 2026
7d82d4c
vfs: use path.posix methods instead of custom implementations
mcollina Feb 4, 2026
3dec83b
vfs: address review feedback for SEA docs and getSeaVfs
mcollina Feb 4, 2026
56c5473
vfs: refactor SEA VFS with initSeaVfs/getSeaVfs pattern
mcollina Feb 5, 2026
f792630
vfs: address test review feedback
mcollina Feb 5, 2026
b9984f5
vfs: replace custom path helpers with standard path module
mcollina Feb 5, 2026
3086170
vfs: address remaining review feedback from avivkeller
mcollina Feb 5, 2026
d8b4469
test: expand VFS provider and promises test coverage
mcollina Feb 6, 2026
fcea5a3
fixup! test: expand VFS provider and promises test coverage
mcollina Feb 10, 2026
b04da60
doc: address vfs documentation review feedback
mcollina Feb 10, 2026
2bcb72a
test: add Windows-specific VFS mount path tests
mcollina Feb 10, 2026
89dd3f1
vfs: address code review feedback
mcollina Feb 10, 2026
cfe3012
vfs: add process vfs-mount and vfs-unmount events
mcollina Feb 11, 2026
8109d84
vfs: address code review feedback
mcollina Feb 12, 2026
286bf37
doc: add case sensitivity documentation for VFS overlay mode
mcollina Feb 12, 2026
3801684
sea: use wrapModuleLoad for VFS module loading
mcollina Feb 13, 2026
90fc3eb
doc: add VFS limitations and cross-references
mcollina Feb 13, 2026
4b7faa4
vfs: fix path normalization on Windows
mcollina Feb 13, 2026
3afa459
sea,vfs: address review feedback from Joyee
mcollina Feb 18, 2026
a735cd0
test: use relative require in SEA VFS test
mcollina Feb 18, 2026
43ed8d4
sea,vfs: fix C++ formatting and markdown link ordering
mcollina Feb 18, 2026
4a66102
doc: address Joyee's documentation review feedback
mcollina Feb 19, 2026
606185e
sea,vfs: address Joyee's code review feedback
mcollina Feb 19, 2026
16a17ae
test: add buffer independence and SEA VFS coverage tests
mcollina Feb 19, 2026
4f8e6de
sea: fix C++ compilation errors in Initialize
mcollina Feb 19, 2026
dd13aff
vfs: replace fs patching with toggleable toRealPath for module loading
mcollina Feb 20, 2026
b931747
vfs: extend toggleable wrappers to readFileSync and internalModuleStat
mcollina Feb 22, 2026
669e9a0
vfs: make package.json reader VFS-aware
mcollina Feb 23, 2026
e1d9966
vfs: convert underscore-prefixed methods to private class fields
mcollina Feb 24, 2026
ed86755
test: add missing callback tests for VFS promises test file
mcollina Feb 24, 2026
8386303
vfs: lazy-load esm/formats to fix shared library builds
mcollina Feb 24, 2026
e3c2ffb
test: add VFS bare specifier ESM resolution test
mcollina Feb 25, 2026
03a0242
vfs: replace monkeypatching with self-contained module.registerHooks
mcollina Feb 25, 2026
77ad8b8
test: add comprehensive VFS module hooks coverage tests
mcollina Feb 25, 2026
93bd576
vfs: address review feedback for module_hooks and file_system
mcollina Feb 26, 2026
306b825
test: use descriptive mount paths in VFS ESM import tests
mcollina Feb 27, 2026
6cd90e1
test: add VFS internals coverage tests
mcollina Feb 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions doc/api/fs.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,36 @@ try {
}
```

## Virtual File System (VFS) support

<!-- YAML
added: REPLACEME
-->

> Stability: 1 - Experimental

The `fs` module can operate on virtual files when the [`node:vfs`][] module is
used. When a virtual file system is mounted, `fs` operations on paths under
the mount point are automatically routed to the VFS instead of the real file
system.

```cjs
const vfs = require('node:vfs');
const fs = require('node:fs');

const myVfs = vfs.create();
myVfs.writeFileSync('/data.txt', 'Hello from VFS');
myVfs.mount('/virtual');

// This reads from the virtual file system
fs.readFileSync('/virtual/data.txt', 'utf8'); // 'Hello from VFS'

myVfs.unmount();
```

Not all `fs` operations are supported with VFS. See the [`node:vfs`][]
documentation for the complete list of supported operations and limitations.

## Promises API

<!-- YAML
Expand Down Expand Up @@ -8779,6 +8809,7 @@ the file contents.
[`inotify(7)`]: https://man7.org/linux/man-pages/man7/inotify.7.html
[`kqueue(2)`]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
[`minimatch`]: https://github.com/isaacs/minimatch
[`node:vfs`]: vfs.md
[`util.promisify()`]: util.md#utilpromisifyoriginal
[bigints]: https://tc39.github.io/proposal-bigint
[caveats]: #caveats
Expand Down
1 change: 1 addition & 0 deletions doc/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
* [URL](url.md)
* [Utilities](util.md)
* [V8](v8.md)
* [Virtual File System](vfs.md)
* [VM](vm.md)
* [WASI](wasi.md)
* [Web Crypto API](webcrypto.md)
Expand Down
71 changes: 71 additions & 0 deletions doc/api/single-executable-applications.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ The configuration currently reads the following top-level fields:
"disableExperimentalSEAWarning": true, // Default: false
"useSnapshot": false, // Default: false
"useCodeCache": true, // Default: false
"useVfs": true, // Default: false
"execArgv": ["--no-warnings", "--max-old-space-size=4096"], // Optional
"execArgvExtension": "env", // Default: "env", options: "none", "env", "cli"
"assets": { // Optional
Expand Down Expand Up @@ -175,6 +176,74 @@ const raw = getRawAsset('a.jpg');
See documentation of the [`sea.getAsset()`][], [`sea.getAssetAsBlob()`][],
[`sea.getRawAsset()`][] and [`sea.getAssetKeys()`][] APIs for more information.

### Virtual File System (VFS) for assets

> Stability: 1 - Experimental

In addition to using the `node:sea` API to access individual assets, you can use
the Virtual File System (VFS) to access bundled assets through standard `fs`
APIs. To enable VFS, set `"useVfs": true` in the SEA configuration. When
enabled, the VFS is automatically initialized and mounted at `/sea`. All
assets defined in the SEA configuration are accessible through this virtual
path.

```cjs
const fs = require('node:fs');

// Assets are automatically available at /sea when running as SEA
const rawConfig = fs.readFileSync('/sea/config.json', 'utf8');
const data = fs.readFileSync('/sea/data/file.txt');

const config = JSON.parse(rawConfig);

// Directory operations work too
const files = fs.readdirSync('/sea/assets');

// Check if a bundled file exists
if (fs.existsSync('/sea/optional.json')) {
// ...
}
```

The VFS supports all common `fs` operations for reading files and directories.
Since the SEA VFS is read-only, write operations are not supported. See the
[VFS documentation][] for the full list of supported and unsupported operations.

#### Loading modules from VFS in SEA

When `useVfs` is enabled, `require()` in the injected main script uses the
registered module hooks to load modules from the virtual file system. This
supports both absolute VFS paths and relative requires (e.g.,
`require('./helper.js')` from a VFS module), as well as `node_modules` package
lookups.

```cjs
// Require bundled modules using relative paths
const myModule = require('./lib/mymodule.js');
const utils = require('./utils/helpers.js');

// Absolute VFS paths also work
const config = require('/sea/config.json');
```

When `useVfs` is enabled, `__filename` and `__dirname` in the injected main
script reflect VFS paths (e.g., `/sea/main.js`) instead of
[`process.execPath`][].

#### Code caching limitations

The `useCodeCache` option in the SEA configuration does not currently apply to
modules loaded from the VFS. This is a current limitation due to incomplete
implementation, not a technical impossibility. Consider bundling the application
to enable code caching and do not rely on module loading in VFS.

#### Native addon limitations

Native addons (`.node` files) cannot be loaded directly from the VFS because
`process.dlopen()` requires files on the real file system. To use native
addons in a SEA with VFS, write the asset to a temporary file first. See
[Using native addons in the injected main script][] for an example.

### Startup snapshot support

The `useSnapshot` field can be used to enable startup snapshot support. In this
Expand Down Expand Up @@ -646,6 +715,8 @@ to help us document them.
[Generating single executable preparation blobs]: #1-generating-single-executable-preparation-blobs
[Mach-O]: https://en.wikipedia.org/wiki/Mach-O
[PE]: https://en.wikipedia.org/wiki/Portable_Executable
[Using native addons in the injected main script]: #using-native-addons-in-the-injected-main-script
[VFS documentation]: vfs.md
[Windows SDK]: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
[`process.execPath`]: process.md#processexecpath
[`require()`]: modules.md#requireid
Expand Down
89 changes: 89 additions & 0 deletions doc/api/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -2401,6 +2401,94 @@ test('mocks a counting function', (t) => {
});
```

### `mock.fs([options])`

<!-- YAML
added: REPLACEME
-->

> Stability: 1.0 - Early development

* `options` {Object} Optional configuration options for the mock file system.
The following properties are supported:
* `prefix` {string} The mount point prefix for the virtual file system.
**Default:** `'/mock'`.
* `files` {Object} An optional object where keys are file paths (relative to
the VFS root) and values are the file contents. Contents can be strings,
Buffers, or functions that return strings/Buffers.
* Returns: {MockFSContext} An object that can be used to manage the mock file
system.

This function creates a mock file system using the [Virtual File System (VFS)][].
The mock file system is automatically cleaned up when the test completes.

## Class: `MockFSContext`

The `MockFSContext` object is returned by `mock.fs()` and provides the
following methods and properties:

* `vfs` {VirtualFileSystem} The underlying VFS instance.
* `prefix` {string} The mount prefix.
* `addFile(path, content)` Adds a file to the mock file system.
* `addDirectory(path[, populate])` Adds a directory to the mock file system.
* `existsSync(path)` Checks if a path exists (path is relative to prefix).
* `restore()` Manually restores the file system to its original state.

The following example demonstrates how to create a mock file system for testing:

```js
const { test } = require('node:test');
const assert = require('node:assert');
const fs = require('node:fs');

test('reads configuration from mock file', (t) => {
const mockFs = t.mock.fs({
prefix: '/app',
files: {
'/config.json': JSON.stringify({ debug: true }),
'/data/users.txt': 'user1\nuser2\nuser3',
},
});

// Files are accessible via standard fs APIs
const config = JSON.parse(fs.readFileSync('/app/config.json', 'utf8'));
assert.strictEqual(config.debug, true);

// Check file existence
assert.strictEqual(fs.existsSync('/app/config.json'), true);
assert.strictEqual(fs.existsSync('/app/missing.txt'), false);

// Use mockFs.existsSync for paths relative to prefix
assert.strictEqual(mockFs.existsSync('/config.json'), true);
});

test('supports dynamic file content', (t) => {
let counter = 0;
const mockFs = t.mock.fs({ prefix: '/dynamic' });

mockFs.addFile('/counter.txt', () => {
counter++;
return String(counter);
});

// Each read calls the function
assert.strictEqual(fs.readFileSync('/dynamic/counter.txt', 'utf8'), '1');
assert.strictEqual(fs.readFileSync('/dynamic/counter.txt', 'utf8'), '2');
});

test('supports require from mock files', (t) => {
t.mock.fs({
prefix: '/modules',
files: {
'/math.js': 'module.exports = { add: (a, b) => a + b };',
},
});

const math = require('/modules/math.js');
assert.strictEqual(math.add(2, 3), 5);
});
```

### `mock.getter(object, methodName[, implementation][, options])`

<!-- YAML
Expand Down Expand Up @@ -4261,3 +4349,4 @@ Can be used to abort test subtasks when the test has been aborted.
[suite options]: #suitename-options-fn
[test reporters]: #test-reporters
[test runner execution model]: #test-runner-execution-model
[virtual file system (vfs)]: vfs.md
Loading
Loading