Skip to content

feat(vfs): lazy file content loading for InMemoryFs #912

@chaliy

Description

@chaliy

Problem

InMemoryFs stores all file content eagerly as Vec<u8> at mount time. When mounting large file sets (e.g. a repository with thousands of files), all content is loaded into memory upfront, even though scripts typically touch only a fraction of files.

Current implementation

crates/bashkit/src/fs/memory.rs:172-189FsEntry::File always stores content: Vec<u8>. The add_file() method at line 772 immediately calls content.to_vec().

JS bindings (crates/bashkit-js/src/lib.rs:151-164) accept files: Option<HashMap<String, String>> — string content only, no callbacks.

Python bindings similarly accept eager string content.

Proposed approach

Add a lazy variant to FsEntry:

enum FsEntry {
    File { content: Vec<u8>, metadata: Metadata },
    LazyFile { loader: Box<dyn FnOnce() -> Vec<u8> + Send + Sync>, metadata: Metadata },
    // ... existing variants
}

Key behaviors:

  • Loaded on first read: When a lazy file is read, the loader is called and the entry is replaced with a regular File
  • Skipped if written before read: If a script writes to a lazy file before reading it, the loader is never called
  • Cached after first load: Once loaded, behaves identically to a regular file
  • Stat without loading: stat() should return metadata without triggering the load

Binding support

  • JS: Accept files values as either strings or callback functions
  • Python: Accept callables alongside string content
  • Rust: builder.mount_lazy(path, || read_file_content(path))

References

  • Inspired by just-bash #115 which added functions as file content suppliers for InMemoryFs

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions