From e92bb42bef374903d75886af3d7c97ae0306dccc Mon Sep 17 00:00:00 2001 From: Andrew Mackross Date: Wed, 18 Mar 2026 23:12:29 +0100 Subject: [PATCH] Add fs.FS mount option --- eval_test.go | 20 ++++++++++++++++++++ options.go | 2 ++ options_test.go | 19 +++++++++++++++++++ runtime.go | 9 ++++++--- 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/eval_test.go b/eval_test.go index e282163..772df42 100644 --- a/eval_test.go +++ b/eval_test.go @@ -3,6 +3,7 @@ package qjs_test import ( "path" "testing" + "testing/fstest" "github.com/fastschema/qjs" "github.com/stretchr/testify/assert" @@ -377,6 +378,25 @@ func TestModuleLoading(t *testing.T) { } runEvalTests(t, tests, "./testdata/00_loader") }) + + t.Run("FS_Module_Imports", func(t *testing.T) { + rt := must(qjs.New(qjs.Option{ + FS: fstest.MapFS{ + "math-utils.js": &fstest.MapFile{ + Data: []byte("export function add(a, b) { return a + b; }"), + }, + "main.js": &fstest.MapFile{ + Data: []byte("import { add } from 'math-utils.js'; export default String(add(5, 5));"), + }, + }, + })) + defer rt.Close() + + val, err := rt.Eval("main.js", qjs.TypeModule()) + defer val.Free() + assert.NoError(t, err) + assert.Equal(t, "10", val.String()) + }) } // Compilation Tests diff --git a/options.go b/options.go index df515c3..898f3b8 100644 --- a/options.go +++ b/options.go @@ -3,6 +3,7 @@ package qjs import ( "context" "fmt" + "io/fs" "io" "os" ) @@ -32,6 +33,7 @@ const ( type Option struct { CWD string + FS fs.FS StartFunctionName string Context context.Context // Enabling this option significantly increases evaluation time diff --git a/options_test.go b/options_test.go index edcf81e..680ab52 100644 --- a/options_test.go +++ b/options_test.go @@ -4,6 +4,7 @@ import ( "os" "path/filepath" "testing" + "testing/fstest" "github.com/fastschema/qjs" "github.com/stretchr/testify/assert" @@ -66,6 +67,24 @@ func TestEvalOptions(t *testing.T) { }) }) + t.Run("FSOption", func(t *testing.T) { + runtime, err := qjs.New(qjs.Option{ + FS: fstest.MapFS{ + "main.js": &fstest.MapFile{ + Data: []byte("export default 'from fs'"), + }, + }, + }) + require.NoError(t, err) + defer runtime.Close() + + val, err := runtime.Eval("main.js", qjs.TypeModule()) + require.NoError(t, err) + defer val.Free() + + assert.Equal(t, "from fs", val.String()) + }) + t.Run("CodeOption", func(t *testing.T) { runtime := must(qjs.New()) defer runtime.Close() diff --git a/runtime.go b/runtime.go index f099bc3..6f6fcc3 100644 --- a/runtime.go +++ b/runtime.go @@ -132,9 +132,12 @@ func New(options ...Option) (runtime *Runtime, err error) { return nil, fmt.Errorf("failed to setup host module: %w", err) } - fsConfig := wazero. - NewFSConfig(). - WithDirMount(runtime.option.CWD, "/") + fsConfig := wazero.NewFSConfig() + if runtime.option.FS != nil { + fsConfig = fsConfig.WithFSMount(runtime.option.FS, "/") + } else { + fsConfig = fsConfig.WithDirMount(runtime.option.CWD, "/") + } if runtime.module, err = runtime.wrt.InstantiateModule( option.Context, compiledQJSModule,