Skip to content

Add virtual filesystem support for module imports#481

Open
ganehag wants to merge 2 commits into
d5:masterfrom
ganehag:feature/vfs-import
Open

Add virtual filesystem support for module imports#481
ganehag wants to merge 2 commits into
d5:masterfrom
ganehag:feature/vfs-import

Conversation

@ganehag
Copy link
Copy Markdown
Contributor

@ganehag ganehag commented Apr 29, 2026

File-based imports currently require modules to exist on the OS filesystem. That makes Tengo harder to use in sandboxed environments, when embedding scripts into a binary, or when writing isolated unit tests without temporary files.

This changeset adds SetImportFS(fsys fs.FS) to both Script and Compiler. When set, imports are resolved and read through the provided fs.FS instead of the OS filesystem. Relative imports such as import("./sibling") are supported by tracking the current module directory as a forward-slash path, giving consistent behaviour across platforms.

The changeset also adds MultiFS, which layers multiple fs.FS values in priority order. This supports the common case where a base module archive needs to be partially overridden without changing import statements in scripts.

Because fs.FS is a standard library interface, this works out of the box with embed.FS, testing/fstest.MapFS, fs.Sub, and third-party filesystem adapters such as zip, tar, S3-backed filesystems, and similar implementations.

This requires raising the minimum supported Go version from 1.13 to 1.16. Given that Go 1.13 is now several years old, and Go 1.16 introduced useful standard-library support such as io/fs, I think this is a reasonable tradeoff.

ganehag added 2 commits April 29, 2026 10:39
Script.SetImportFS and Compiler.SetImportFS accept any fs.FS as the
source for file-based imports. Modules are resolved and read through
the FS rather than the OS, which enables sandboxed execution, embedded
script bundles (embed.FS), in-memory testing (fstest.MapFS), and
custom backends such as tar archives or databases.

Relative imports (import("./sibling")) work correctly across the VFS:
the compiler tracks the current module directory as a plain forward-
slash string, making behaviour identical on all platforms.

MultiFS layers multiple fs.FS values in priority order, allowing a
base archive to be patched by an overlay without any changes to the
import statements in the scripts themselves.

Bumps the minimum Go version from 1.13 to 1.16 to pick up io/fs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant