vfs: add --vfs-load to run modules from a mount - #8
Draft
pipobscure wants to merge 1 commit into
Draft
Conversation
Builds on --vfs-mount to make a mount a real execution environment, resolving require()/import inside it. Adds --vfs-load, which runs the entry point (process.argv[1]) and all subsequent require()/import resolution against the last --vfs-mount rather than the real file system. process.argv[1] becomes that mount's root, as if `node <mountPoint>` had been run, so the mount's own package.json "main"/index.js selects the entry point and positional arguments are the program's own. A self-mounting shebang (`#!/usr/bin/env -S node --vfs-load --vfs-mount`) therefore makes an archive directly executable. --vfs-load requires at least one --vfs-mount, and workers inherit it alongside the mounts. Making resolution VFS-aware requires four of the CJS/ESM loader's resolution primitives - package.json reading, nearest-parent/scope lookup, legacy main resolution, and extensionless-file format sniffing - to stop bypassing the public fs module and call it instead, since that bypass is what let them ignore a mount. Each defers to the real native binding unchanged for anything outside an active mount. A lean mount registry (internal/vfs/registry) is extracted from internal/vfs/setup so the resolution fast path can answer "is this path under a mount?" without loading the heavier setup/provider machinery. Provider selection - and, for a --vfs-load entry, its resolution - is deferred until after -r and --import preload modules have run, so a provider registered from either backs the mount. Native addons are supported: a directory-backed mount dlopens the real underlying file directly (RealFSProvider.toRealPath); an archive-backed mount extracts the addon to a content-hashed temp file first, scoped per pid so processes don't clobber each other's extractions. Signed-off-by: Philipp Dunkel <pip@pipobscure.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds on --vfs-mount to make a mount a real execution environment, resolving require()/import inside it.
Adds --vfs-load, which runs the entry point (process.argv[1]) and all subsequent require()/import resolution against the last --vfs-mount rather than the real file system. process.argv[1] becomes that mount's root, as if
node <mountPoint>had been run, so the mount's own package.json "main"/index.js selects the entry point and positional arguments are the program's own. A self-mounting shebang (#!/usr/bin/env -S node --vfs-load --vfs-mount) therefore makes an archive directly executable. --vfs-load requires at least one --vfs-mount, and workers inherit it alongside the mounts.Making resolution VFS-aware requires four of the CJS/ESM loader's resolution primitives - package.json reading, nearest-parent/scope lookup, legacy main resolution, and extensionless-file format sniffing - to stop bypassing the public fs module and call it instead, since that bypass is what let them ignore a mount. Each defers to the real native binding unchanged for anything outside an active mount. A lean mount registry (internal/vfs/registry) is extracted from internal/vfs/setup so the resolution fast path can answer "is this path under a mount?" without loading the heavier setup/provider machinery.
Provider selection - and, for a --vfs-load entry, its resolution - is deferred until after -r and --import preload modules have run, so a provider registered from either backs the mount.
Native addons are supported: a directory-backed mount dlopens the real underlying file directly (RealFSProvider.toRealPath); an archive-backed mount extracts the addon to a content-hashed temp file first, scoped per pid so processes don't clobber each other's extractions.