Repository: tetratelabs/wazero
Pull request #399 (2022-03-20 03:24:59)

wasi: moves test-only overrides out of config, simplifies error tests
This moves test-only overrides out of config in preparation of
normalized configuration. This also simplifies error tests by using the
API directly for all cases except exit.


Patch:
diff --git a/README.md b/README.md
index 6f53099e..8e15ac8c 100644
--- a/README.md
+++ b/README.md
@@ -160,7 +160,7 @@ are not W3C recommendations (standards). This means they can change further
 between now and any future update to the W3C WebAssembly core specification.
 Due to this, we cannot guarantee future compatability. Please encourage the
 [WebAssembly community](https://www.w3.org/community/webassembly/) to formalize
-features you rely on, specifically to read the W3C recommendation (REC) phase.
+features you rely on, specifically to reach the W3C recommendation (REC) phase.
 
 ### WebAssembly System Interface (WASI)
 
diff --git a/internal/wasi/wasi.go b/internal/wasi/wasi.go
index 98c0d634..537f8ba7 100644
--- a/internal/wasi/wasi.go
+++ b/internal/wasi/wasi.go
@@ -960,13 +960,16 @@ type SnapshotPreview1 interface {
 type wasiAPI struct {
 	// cfg is the default configuration to use when there is no context.Context override (ConfigContextKey).
 	cfg *Config
+	// timeNowUnixNano is mutable for testing
+	timeNowUnixNano func() uint64
+	randSource      func([]byte) error
 }
 
 // SnapshotPreview1Functions returns all go functions that implement SnapshotPreview1.
 // These should be exported in the module named wasi.ModuleSnapshotPreview1.
 // See internalwasm.NewHostModule
-func SnapshotPreview1Functions(config *Config) (nameToGoFunc map[string]interface{}) {
-	a := NewAPI(config)
+func SnapshotPreview1Functions(config *Config) (a *wasiAPI, nameToGoFunc map[string]interface{}) {
+	a = NewAPI(config)
 	// Note: these are ordered per spec for consistency even if the resulting map can't guarantee that.
 	// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#functions
 	nameToGoFunc = map[string]interface{}{
@@ -1090,10 +1093,8 @@ func (a *wasiAPI) ClockResGet(ctx wasm.Module, id uint32, resultResolution uint3
 
 // ClockTimeGet implements SnapshotPreview1.ClockTimeGet
 func (a *wasiAPI) ClockTimeGet(ctx wasm.Module, id uint32, precision uint64, resultTimestamp uint32) wasi.Errno {
-	cfg := a.config(ctx.Context())
-
 	// TODO: id and precision are currently ignored.
-	if !ctx.Memory().WriteUint64Le(resultTimestamp, cfg.timeNowUnixNano()) {
+	if !ctx.Memory().WriteUint64Le(resultTimestamp, a.timeNowUnixNano()) {
 		return wasi.ErrnoFault
 	}
 	return wasi.ErrnoSuccess
@@ -1513,10 +1514,8 @@ func (a *wasiAPI) SchedYield(ctx wasm.Module) wasi.Errno {
 
 // RandomGet implements SnapshotPreview1.RandomGet
 func (a *wasiAPI) RandomGet(ctx wasm.Module, buf uint32, bufLen uint32) (errno wasi.Errno) {
-	cfg := a.config(ctx.Context())
-
 	randomBytes := make([]byte, bufLen)
-	err := cfg.randSource(randomBytes)
+	err := a.randSource(randomBytes)
 	if err != nil {
 		// TODO: handle different errors that syscal to entropy source can return
 		return wasi.ErrnoIo
@@ -1562,9 +1561,6 @@ type Config struct {
 	stdout,
 	stderr io.Writer
 	opened map[uint32]fileEntry
-	// timeNowUnixNano is mutable for testing
-	timeNowUnixNano func() uint64
-	randSource      func([]byte) error
 }
 
 func (c *Config) Stdin(reader io.Reader) {
@@ -1630,6 +1626,13 @@ func NewConfig() *Config {
 		stdout:  os.Stdout,
 		stderr:  os.Stderr,
 		opened:  map[uint32]fileEntry{},
+	}
+}
+
+// NewAPI is exported for benchmarks
+func NewAPI(config *Config) *wasiAPI {
+	return &wasiAPI{
+		cfg: config,
 		timeNowUnixNano: func() uint64 {
 			return uint64(time.Now().UnixNano())
 		},
@@ -1640,11 +1643,6 @@ func NewConfig() *Config {
 	}
 }
 
-// NewAPI is exported for benchmarks
-func NewAPI(config *Config) *wasiAPI {
-	return &wasiAPI{cfg: config} // Safe copy
-}
-
 // config returns a potentially overridden Config.
 func (a *wasiAPI) config(ctx context.Context) *Config {
 	if cfg := ctx.Value(ConfigContextKey{}); cfg != nil {
@@ -1655,7 +1653,7 @@ func (a *wasiAPI) config(ctx context.Context) *Config {
 
 func (a *wasiAPI) randUnusedFD(config *Config) (uint32, error) {
 	rand := make([]byte, 4)
-	err := config.randSource(rand)
+	err := a.randSource(rand)
 	if err != nil {
 		return 0, err
 	}
diff --git a/wasi.go b/wasi.go
index de83648b..c96d7b27 100644
--- a/wasi.go
+++ b/wasi.go
@@ -75,7 +75,8 @@ func WASISnapshotPreview1() *Module {
 // WASISnapshotPreview1WithConfig are functions importable as the module name wasi.ModuleSnapshotPreview1
 func WASISnapshotPreview1WithConfig(c *WASIConfig) *Module {
 	cfg := newConfig(c) // safe copy of config
-	m, err := internalwasm.NewHostModule(wasi.ModuleSnapshotPreview1, internalwasi.SnapshotPreview1Functions(cfg))
+	_, fns := internalwasi.SnapshotPreview1Functions(cfg)
+	m, err := internalwasm.NewHostModule(wasi.ModuleSnapshotPreview1, fns)
 	if err != nil {
 		panic(fmt.Errorf("BUG: %w", err))
 	}


Test patch:
diff --git a/internal/wasi/wasi_test.go b/internal/wasi/wasi_test.go
index 4d6d14b6..c2ada1b7 100644
--- a/internal/wasi/wasi_test.go
+++ b/internal/wasi/wasi_test.go
@@ -77,13 +77,13 @@ func TestSnapshotPreview1_ArgsGet(t *testing.T) {
 		'?', // stopped after encoding
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionArgsGet, ImportArgsGet, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionArgsGet, ImportArgsGet, moduleName, config)
 
 	t.Run("SnapshotPreview1.ArgsGet", func(t *testing.T) {
 		maskMemory(t, mod, len(expectedMemory))
 
 		// Invoke ArgsGet directly and check the memory side effects.
-		errno := NewAPI(config).ArgsGet(mod, argv, argvBuf)
+		errno := a.ArgsGet(mod, argv, argvBuf)
 		require.Equal(t, wasi.ErrnoSuccess, errno)
 
 		actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory)))
@@ -109,7 +109,7 @@ func TestSnapshotPreview1_ArgsGet_Errors(t *testing.T) {
 	config := NewConfig()
 	err := config.Args("a", "bc")
 	require.NoError(t, err)
-	mod, fn := instantiateModule(t, ctx, FunctionArgsGet, ImportArgsGet, moduleName, config)
+	a, mod, _ := instantiateModule(t, ctx, FunctionArgsGet, ImportArgsGet, moduleName, config)
 
 	memorySize := mod.Memory().Size()
 	validAddress := uint32(0) // arbitrary valid address as arguments to args_get. We chose 0 here.
@@ -147,9 +147,9 @@ func TestSnapshotPreview1_ArgsGet_Errors(t *testing.T) {
 		tc := tt
 
 		t.Run(tc.name, func(t *testing.T) {
-			results, err := fn.Call(mod, uint64(tc.argv), uint64(tc.argvBuf))
+			errno := a.ArgsGet(mod, tc.argv, tc.argvBuf)
 			require.NoError(t, err)
-			require.Equal(t, uint64(wasi.ErrnoFault), results[0]) // results[0] is the errno
+			require.Equal(t, wasi.ErrnoFault, errno)
 		})
 	}
 }
@@ -170,13 +170,13 @@ func TestSnapshotPreview1_ArgsSizesGet(t *testing.T) {
 		'?', // stopped after encoding
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionArgsSizesGet, ImportArgsSizesGet, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionArgsSizesGet, ImportArgsSizesGet, moduleName, config)
 
 	t.Run("SnapshotPreview1.ArgsSizesGet", func(t *testing.T) {
 		maskMemory(t, mod, len(expectedMemory))
 
 		// Invoke ArgsSizesGet directly and check the memory side effects.
-		errno := NewAPI(config).ArgsSizesGet(mod, resultArgc, resultArgvBufSize)
+		errno := a.ArgsSizesGet(mod, resultArgc, resultArgvBufSize)
 		require.Equal(t, wasi.ErrnoSuccess, errno)
 
 		actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory)))
@@ -203,7 +203,7 @@ func TestSnapshotPreview1_ArgsSizesGet_Errors(t *testing.T) {
 	err := config.Args("a", "bc")
 	require.NoError(t, err)
 
-	mod, fn := instantiateModule(t, ctx, FunctionArgsSizesGet, ImportArgsSizesGet, moduleName, config)
+	a, mod, _ := instantiateModule(t, ctx, FunctionArgsSizesGet, ImportArgsSizesGet, moduleName, config)
 
 	memorySize := mod.Memory().Size()
 	validAddress := uint32(0) // arbitrary valid address as arguments to args_sizes_get. We chose 0 here.
@@ -239,9 +239,9 @@ func TestSnapshotPreview1_ArgsSizesGet_Errors(t *testing.T) {
 		tc := tt
 
 		t.Run(tc.name, func(t *testing.T) {
-			results, err := fn.Call(mod, uint64(tc.argc), uint64(tc.argvBufSize))
+			errno := a.ArgsSizesGet(mod, tc.argc, tc.argvBufSize)
 			require.NoError(t, err)
-			require.Equal(t, uint64(wasi.ErrnoFault), results[0]) // results[0] is the errno
+			require.Equal(t, wasi.ErrnoFault, errno)
 		})
 	}
 }
@@ -301,13 +301,13 @@ func TestSnapshotPreview1_EnvironGet(t *testing.T) {
 		'?', // stopped after encoding
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionEnvironGet, ImportEnvironGet, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionEnvironGet, ImportEnvironGet, moduleName, config)
 
 	t.Run("SnapshotPreview1.EnvironGet", func(t *testing.T) {
 		maskMemory(t, mod, len(expectedMemory))
 
 		// Invoke EnvironGet directly and check the memory side effects.
-		errno := NewAPI(config).EnvironGet(mod, resultEnviron, resultEnvironBuf)
+		errno := a.EnvironGet(mod, resultEnviron, resultEnvironBuf)
 		require.Equal(t, wasi.ErrnoSuccess, errno)
 
 		actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory)))
@@ -334,7 +334,7 @@ func TestSnapshotPreview1_EnvironGet_Errors(t *testing.T) {
 	err := config.Environ("a=bc", "b=cd")
 	require.NoError(t, err)
 
-	mod, fn := instantiateModule(t, ctx, FunctionEnvironGet, ImportEnvironGet, moduleName, config)
+	a, mod, _ := instantiateModule(t, ctx, FunctionEnvironGet, ImportEnvironGet, moduleName, config)
 
 	memorySize := mod.Memory().Size()
 	validAddress := uint32(0) // arbitrary valid address as arguments to environ_get. We chose 0 here.
@@ -372,9 +372,9 @@ func TestSnapshotPreview1_EnvironGet_Errors(t *testing.T) {
 		tc := tt
 
 		t.Run(tc.name, func(t *testing.T) {
-			results, err := fn.Call(mod, uint64(tc.environ), uint64(tc.environBuf))
+			errno := a.EnvironGet(mod, tc.environ, tc.environBuf)
 			require.NoError(t, err)
-			require.Equal(t, uint64(wasi.ErrnoFault), results[0]) // results[0] is the errno
+			require.Equal(t, wasi.ErrnoFault, errno)
 		})
 	}
 }
@@ -395,13 +395,13 @@ func TestSnapshotPreview1_EnvironSizesGet(t *testing.T) {
 		'?', // stopped after encoding
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionEnvironSizesGet, ImportEnvironSizesGet, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionEnvironSizesGet, ImportEnvironSizesGet, moduleName, config)
 
 	t.Run("SnapshotPreview1.EnvironSizesGet", func(t *testing.T) {
 		maskMemory(t, mod, len(expectedMemory))
 
 		// Invoke EnvironSizesGet directly and check the memory side effects.
-		errno := NewAPI(config).EnvironSizesGet(mod, resultEnvironc, resultEnvironBufSize)
+		errno := a.EnvironSizesGet(mod, resultEnvironc, resultEnvironBufSize)
 		require.Equal(t, wasi.ErrnoSuccess, errno)
 
 		actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory)))
@@ -428,7 +428,7 @@ func TestSnapshotPreview1_EnvironSizesGet_Errors(t *testing.T) {
 	err := config.Environ("a=b", "b=cd")
 	require.NoError(t, err)
 
-	mod, fn := instantiateModule(t, ctx, FunctionEnvironSizesGet, ImportEnvironSizesGet, moduleName, config)
+	a, mod, _ := instantiateModule(t, ctx, FunctionEnvironSizesGet, ImportEnvironSizesGet, moduleName, config)
 
 	memorySize := mod.Memory().Size()
 	validAddress := uint32(0) // arbitrary valid address as arguments to environ_sizes_get. We chose 0 here.
@@ -464,9 +464,9 @@ func TestSnapshotPreview1_EnvironSizesGet_Errors(t *testing.T) {
 		tc := tt
 
 		t.Run(tc.name, func(t *testing.T) {
-			results, err := fn.Call(mod, uint64(tc.environc), uint64(tc.environBufSize))
+			errno := a.EnvironSizesGet(mod, tc.environc, tc.environBufSize)
 			require.NoError(t, err)
-			require.Equal(t, uint64(wasi.ErrnoFault), results[0]) // results[0] is the errno
+			require.Equal(t, wasi.ErrnoFault, errno)
 		})
 	}
 }
@@ -476,10 +476,10 @@ func TestSnapshotPreview1_ClockResGet(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionClockResGet, ImportClockResGet, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionClockResGet, ImportClockResGet, moduleName, config)
 
 	t.Run("SnapshotPreview1.ClockResGet", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).ClockResGet(mod, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.ClockResGet(mod, 0, 0))
 	})
 
 	t.Run(FunctionClockResGet, func(t *testing.T) {
@@ -500,15 +500,15 @@ func TestSnapshotPreview1_ClockTimeGet(t *testing.T) {
 
 	ctx := context.Background()
 	config := NewConfig()
-	config.timeNowUnixNano = func() uint64 { return epochNanos }
 
-	mod, fn := instantiateModule(t, ctx, FunctionClockTimeGet, ImportClockTimeGet, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionClockTimeGet, ImportClockTimeGet, moduleName, config)
+	a.timeNowUnixNano = func() uint64 { return epochNanos }
 
 	t.Run("SnapshotPreview1.ClockTimeGet", func(t *testing.T) {
 		maskMemory(t, mod, len(expectedMemory))
 
 		// invoke ClockTimeGet directly and check the memory side effects!
-		errno := NewAPI(config).ClockTimeGet(mod, 0 /* TODO: id */, 0 /* TODO: precision */, resultTimestamp)
+		errno := a.ClockTimeGet(mod, 0 /* TODO: id */, 0 /* TODO: precision */, resultTimestamp)
 		require.Equal(t, wasi.ErrnoSuccess, errno)
 
 		actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory)))
@@ -534,9 +534,9 @@ func TestSnapshotPreview1_ClockTimeGet_Errors(t *testing.T) {
 
 	ctx := context.Background()
 	config := NewConfig()
-	config.timeNowUnixNano = func() uint64 { return epochNanos }
 
-	mod, fn := instantiateModule(t, ctx, FunctionClockTimeGet, ImportClockTimeGet, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionClockTimeGet, ImportClockTimeGet, moduleName, config)
+	a.timeNowUnixNano = func() uint64 { return epochNanos }
 
 	memorySize := mod.Memory().Size()
 
@@ -572,10 +572,10 @@ func TestSnapshotPreview1_FdAdvise(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdAdvise, ImportFdAdvise, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdAdvise, ImportFdAdvise, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdAdvise", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdAdvise(mod, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdAdvise(mod, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionFdAdvise, func(t *testing.T) {
@@ -590,10 +590,10 @@ func TestSnapshotPreview1_FdAllocate(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdAllocate, ImportFdAllocate, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdAllocate, ImportFdAllocate, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdAllocate", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdAllocate(mod, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdAllocate(mod, 0, 0, 0))
 	})
 
 	t.Run(FunctionFdAllocate, func(t *testing.T) {
@@ -623,8 +623,8 @@ func TestSnapshotPreview1_FdClose(t *testing.T) {
 			},
 		}
 
-		mod, fn := instantiateModule(t, ctx, FunctionFdClose, ImportFdClose, moduleName, config)
-		return mod, fn, NewAPI(config)
+		a, mod, fn := instantiateModule(t, ctx, FunctionFdClose, ImportFdClose, moduleName, config)
+		return mod, fn, a
 	}
 
 	t.Run("SnapshotPreview1.FdClose", func(t *testing.T) {
@@ -657,10 +657,10 @@ func TestSnapshotPreview1_FdDatasync(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdDatasync, ImportFdDatasync, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdDatasync, ImportFdDatasync, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdDatasync", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdDatasync(mod, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdDatasync(mod, 0))
 	})
 
 	t.Run(FunctionFdDatasync, func(t *testing.T) {
@@ -677,10 +677,10 @@ func TestSnapshotPreview1_FdFdstatSetFlags(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdFdstatSetFlags, ImportFdFdstatSetFlags, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdFdstatSetFlags, ImportFdFdstatSetFlags, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdFdstatSetFlags", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdFdstatSetFlags(mod, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdFdstatSetFlags(mod, 0, 0))
 	})
 
 	t.Run(FunctionFdFdstatSetFlags, func(t *testing.T) {
@@ -695,10 +695,10 @@ func TestSnapshotPreview1_FdFdstatSetRights(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdFdstatSetRights, ImportFdFdstatSetRights, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdFdstatSetRights, ImportFdFdstatSetRights, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdFdstatSetRights", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdFdstatSetRights(mod, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdFdstatSetRights(mod, 0, 0, 0))
 	})
 
 	t.Run(FunctionFdFdstatSetRights, func(t *testing.T) {
@@ -713,10 +713,10 @@ func TestSnapshotPreview1_FdFilestatGet(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdFilestatGet, ImportFdFilestatGet, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdFilestatGet, ImportFdFilestatGet, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdFilestatGet", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdFilestatGet(mod, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdFilestatGet(mod, 0, 0))
 	})
 
 	t.Run(FunctionFdFilestatGet, func(t *testing.T) {
@@ -731,10 +731,10 @@ func TestSnapshotPreview1_FdFilestatSetSize(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdFilestatSetSize, ImportFdFilestatSetSize, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdFilestatSetSize, ImportFdFilestatSetSize, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdFilestatSetSize", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdFilestatSetSize(mod, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdFilestatSetSize(mod, 0, 0))
 	})
 
 	t.Run(FunctionFdFilestatSetSize, func(t *testing.T) {
@@ -749,10 +749,10 @@ func TestSnapshotPreview1_FdFilestatSetTimes(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdFilestatSetTimes, ImportFdFilestatSetTimes, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdFilestatSetTimes, ImportFdFilestatSetTimes, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdFilestatSetTimes", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdFilestatSetTimes(mod, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdFilestatSetTimes(mod, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionFdFilestatSetTimes, func(t *testing.T) {
@@ -767,10 +767,10 @@ func TestSnapshotPreview1_FdPread(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdPread, ImportFdPread, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdPread, ImportFdPread, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdPread", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdPread(mod, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdPread(mod, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionFdPread, func(t *testing.T) {
@@ -789,7 +789,7 @@ func TestSnapshotPreview1_FdPrestatGet(t *testing.T) {
 		path: "/tmp",
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdPrestatGet, ImportFdPrestatGet, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdPrestatGet, ImportFdPrestatGet, moduleName, config)
 
 	resultPrestat := uint32(1) // arbitrary offset
 	expectedMemory := []byte{
@@ -804,7 +804,7 @@ func TestSnapshotPreview1_FdPrestatGet(t *testing.T) {
 	t.Run("SnapshotPreview1.FdPrestatGet", func(t *testing.T) {
 		maskMemory(t, mod, len(expectedMemory))
 
-		errno := NewAPI(config).FdPrestatGet(mod, fd, resultPrestat)
+		errno := a.FdPrestatGet(mod, fd, resultPrestat)
 		require.Equal(t, wasi.ErrnoSuccess, errno)
 
 		actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory)))
@@ -835,7 +835,7 @@ func TestSnapshotPreview1_FdPrestatGet_Errors(t *testing.T) {
 		fd: {path: "/tmp"},
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdPrestatGet, ImportFdPrestatGet, moduleName, config)
+	a, mod, _ := instantiateModule(t, ctx, FunctionFdPrestatGet, ImportFdPrestatGet, moduleName, config)
 
 	memorySize := mod.Memory().Size()
 
@@ -864,9 +864,8 @@ func TestSnapshotPreview1_FdPrestatGet_Errors(t *testing.T) {
 		tc := tt
 
 		t.Run(tc.name, func(t *testing.T) {
-			results, err := fn.Call(mod, uint64(tc.fd), uint64(tc.resultPrestat))
-			require.NoError(t, err)
-			require.Equal(t, tc.expectedErrno, wasi.Errno(results[0])) // results[0] is the errno
+			errno := a.FdPrestatGet(mod, tc.fd, tc.resultPrestat)
+			require.Equal(t, tc.expectedErrno, errno)
 		})
 	}
 }
@@ -881,7 +880,7 @@ func TestSnapshotPreview1_FdPrestatDirName(t *testing.T) {
 		fileSys: &MemFS{},
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdPrestatDirName, ImportFdPrestatDirName, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdPrestatDirName, ImportFdPrestatDirName, moduleName, config)
 
 	path := uint32(1)    // arbitrary offset
 	pathLen := uint32(3) // shorter than len("/tmp") to test the path is written for the length of pathLen
@@ -894,7 +893,7 @@ func TestSnapshotPreview1_FdPrestatDirName(t *testing.T) {
 	t.Run("SnapshotPreview1.FdPrestatDirName", func(t *testing.T) {
 		maskMemory(t, mod, len(expectedMemory))
 
-		errno := NewAPI(config).FdPrestatDirName(mod, fd, path, pathLen)
+		errno := a.FdPrestatDirName(mod, fd, path, pathLen)
 		require.Equal(t, wasi.ErrnoSuccess, errno)
 
 		actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory)))
@@ -925,7 +924,7 @@ func TestSnapshotPreview1_FdPrestatDirName_Errors(t *testing.T) {
 	}
 	pathLen := uint32(len("/tmp"))
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdPrestatDirName, ImportFdPrestatDirName, moduleName, config)
+	a, mod, _ := instantiateModule(t, ctx, FunctionFdPrestatDirName, ImportFdPrestatDirName, moduleName, config)
 
 	memorySize := mod.Memory().Size()
 	validAddress := uint32(0) // Arbitrary valid address as arguments to fd_prestat_dir_name. We chose 0 here.
@@ -972,9 +971,8 @@ func TestSnapshotPreview1_FdPrestatDirName_Errors(t *testing.T) {
 		tc := tt
 
 		t.Run(tc.name, func(t *testing.T) {
-			results, err := fn.Call(mod, uint64(tc.fd), uint64(tc.path), uint64(tc.pathLen))
-			require.NoError(t, err)
-			require.Equal(t, tc.expectedErrno, wasi.Errno(results[0])) // results[0] is the errno
+			errno := a.FdPrestatDirName(mod, tc.fd, tc.path, tc.pathLen)
+			require.Equal(t, tc.expectedErrno, errno)
 		})
 	}
 }
@@ -984,10 +982,10 @@ func TestSnapshotPreview1_FdPwrite(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdPwrite, ImportFdPwrite, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdPwrite, ImportFdPwrite, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdPwrite", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdPwrite(mod, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdPwrite(mod, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionFdPwrite, func(t *testing.T) {
@@ -1023,7 +1021,7 @@ func TestSnapshotPreview1_FdRead(t *testing.T) {
 		'?',
 	)
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdRead, ImportFdRead, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdRead, ImportFdRead, moduleName, config)
 
 	// TestSnapshotPreview1_FdRead uses a matrix because setting up test files is complicated and has to be clean each time.
 	type fdReadFn func(ctx publicwasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno
@@ -1032,7 +1030,7 @@ func TestSnapshotPreview1_FdRead(t *testing.T) {
 		fdRead func() fdReadFn
 	}{
 		{"SnapshotPreview1.FdRead", func() fdReadFn {
-			return NewAPI(config).FdRead
+			return a.FdRead
 		}},
 		{FunctionFdRead, func() fdReadFn {
 			return func(ctx publicwasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno {
@@ -1069,22 +1067,22 @@ func TestSnapshotPreview1_FdRead(t *testing.T) {
 }
 
 func TestSnapshotPreview1_FdRead_Errors(t *testing.T) {
-	validFD := uint64(3)                                // arbitrary valid fd after 0, 1, and 2, that are stdin/out/err
+	validFD := uint32(3)                                // arbitrary valid fd after 0, 1, and 2, that are stdin/out/err
 	file, memFS := createFile(t, "test_path", []byte{}) // file with empty contents
 
 	ctx := context.Background()
 	config := NewConfig()
-	config.opened[uint32(validFD)] = fileEntry{
+	config.opened[validFD] = fileEntry{
 		path:    "test_path",
 		fileSys: memFS,
 		file:    file,
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdRead, ImportFdRead, moduleName, config)
+	a, mod, _ := instantiateModule(t, ctx, FunctionFdRead, ImportFdRead, moduleName, config)
 
 	tests := []struct {
 		name                            string
-		fd, iovs, iovsCount, resultSize uint64
+		fd, iovs, iovsCount, resultSize uint32
 		memory                          []byte
 		expectedErrno                   wasi.Errno
 	}{
@@ -1151,14 +1149,13 @@ func TestSnapshotPreview1_FdRead_Errors(t *testing.T) {
 	for _, tt := range tests {
 		tc := tt
 		t.Run(tc.name, func(t *testing.T) {
-			offset := wasm.MemoryPagesToBytesNum(testMemoryPageSize) - uint64(len(tc.memory))
+			offset := uint32(wasm.MemoryPagesToBytesNum(testMemoryPageSize) - uint64(len(tc.memory)))
 
-			memoryWriteOK := mod.Memory().Write(uint32(offset), tc.memory)
+			memoryWriteOK := mod.Memory().Write(offset, tc.memory)
 			require.True(t, memoryWriteOK)
 
-			results, err := fn.Call(mod, tc.fd, tc.iovs+offset, tc.iovsCount+offset, tc.resultSize+offset)
-			require.NoError(t, err)
-			require.Equal(t, tc.expectedErrno, wasi.Errno(results[0])) // results[0] is the errno
+			errno := a.FdRead(mod, tc.fd, tc.iovs+offset, tc.iovsCount+offset, tc.resultSize+offset)
+			require.Equal(t, tc.expectedErrno, errno)
 		})
 	}
 }
@@ -1168,10 +1165,10 @@ func TestSnapshotPreview1_FdReaddir(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdReaddir, ImportFdReaddir, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdReaddir, ImportFdReaddir, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdReaddir", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdReaddir(mod, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdReaddir(mod, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionFdReaddir, func(t *testing.T) {
@@ -1186,10 +1183,10 @@ func TestSnapshotPreview1_FdRenumber(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdRenumber, ImportFdRenumber, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdRenumber, ImportFdRenumber, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdRenumber", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdRenumber(mod, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdRenumber(mod, 0, 0))
 	})
 
 	t.Run(FunctionFdRenumber, func(t *testing.T) {
@@ -1212,7 +1209,7 @@ func TestSnapshotPreview1_FdSeek(t *testing.T) {
 		file:    file,
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdSeek, ImportFdSeek, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdSeek, ImportFdSeek, moduleName, config)
 
 	// TestSnapshotPreview1_FdSeek uses a matrix because setting up test files is complicated and has to be clean each time.
 	type fdSeekFn func(ctx publicwasm.Module, fd uint32, offset uint64, whence, resultNewOffset uint32) wasi.Errno
@@ -1221,7 +1218,7 @@ func TestSnapshotPreview1_FdSeek(t *testing.T) {
 		fdSeek func() fdSeekFn
 	}{
 		{"SnapshotPreview1.FdSeek", func() fdSeekFn {
-			return NewAPI(config).FdSeek
+			return a.FdSeek
 		}},
 		{FunctionFdSeek, func() fdSeekFn {
 			return func(ctx publicwasm.Module, fd uint32, offset uint64, whence, resultNewoffset uint32) wasi.Errno {
@@ -1298,23 +1295,25 @@ func TestSnapshotPreview1_FdSeek(t *testing.T) {
 }
 
 func TestSnapshotPreview1_FdSeek_Errors(t *testing.T) {
-	validFD := uint64(3)                                        // arbitrary valid fd after 0, 1, and 2, that are stdin/out/err
+	validFD := uint32(3)                                        // arbitrary valid fd after 0, 1, and 2, that are stdin/out/err
 	file, memFS := createFile(t, "test_path", []byte("wazero")) // arbitrary valid file with non-empty contents
 	ctx := context.Background()
 	config := NewConfig()
-	config.opened[uint32(validFD)] = fileEntry{
+	config.opened[validFD] = fileEntry{
 		path:    "test_path",
 		fileSys: memFS,
 		file:    file,
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdSeek, ImportFdSeek, moduleName, config)
+	a, mod, _ := instantiateModule(t, ctx, FunctionFdSeek, ImportFdSeek, moduleName, config)
 	memorySize := mod.Memory().Size()
 
 	tests := []struct {
-		name                                string
-		fd, offset, whence, resultNewoffset uint64
-		expectedErrno                       wasi.Errno
+		name                    string
+		fd                      uint32
+		offset                  uint64
+		whence, resultNewoffset uint32
+		expectedErrno           wasi.Errno
 	}{
 		{
 			name:          "invalid fd",
@@ -1330,7 +1329,7 @@ func TestSnapshotPreview1_FdSeek_Errors(t *testing.T) {
 		{
 			name:            "out-of-memory writing resultNewoffset",
 			fd:              validFD,
-			resultNewoffset: uint64(memorySize),
+			resultNewoffset: memorySize,
 			expectedErrno:   wasi.ErrnoFault,
 		},
 	}
@@ -1338,9 +1337,8 @@ func TestSnapshotPreview1_FdSeek_Errors(t *testing.T) {
 	for _, tt := range tests {
 		tc := tt
 		t.Run(tc.name, func(t *testing.T) {
-			results, err := fn.Call(mod, tc.fd, tc.offset, tc.whence, tc.resultNewoffset)
-			require.NoError(t, err)
-			require.Equal(t, tc.expectedErrno, wasi.Errno(results[0])) // results[0] is the errno
+			errno := a.FdSeek(mod, tc.fd, tc.offset, tc.whence, tc.resultNewoffset)
+			require.Equal(t, tc.expectedErrno, errno)
 		})
 	}
 
@@ -1351,10 +1349,10 @@ func TestSnapshotPreview1_FdSync(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdSync, ImportFdSync, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdSync, ImportFdSync, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdSync", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdSync(mod, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdSync(mod, 0))
 	})
 
 	t.Run(FunctionFdSync, func(t *testing.T) {
@@ -1369,10 +1367,10 @@ func TestSnapshotPreview1_FdTell(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdTell, ImportFdTell, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdTell, ImportFdTell, moduleName, config)
 
 	t.Run("SnapshotPreview1.FdTell", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).FdTell(mod, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.FdTell(mod, 0, 0))
 	})
 
 	t.Run(FunctionFdTell, func(t *testing.T) {
@@ -1408,7 +1406,7 @@ func TestSnapshotPreview1_FdWrite(t *testing.T) {
 		'?',
 	)
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdWrite, ImportFdWrite, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionFdWrite, ImportFdWrite, moduleName, config)
 
 	// TestSnapshotPreview1_FdWrite uses a matrix because setting up test files is complicated and has to be clean each time.
 	type fdWriteFn func(ctx publicwasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno
@@ -1417,7 +1415,7 @@ func TestSnapshotPreview1_FdWrite(t *testing.T) {
 		fdWrite func() fdWriteFn
 	}{
 		{"SnapshotPreview1.FdWrite", func() fdWriteFn {
-			return NewAPI(config).FdWrite
+			return a.FdWrite
 		}},
 		{FunctionFdWrite, func() fdWriteFn {
 			return func(ctx publicwasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno {
@@ -1454,7 +1452,7 @@ func TestSnapshotPreview1_FdWrite(t *testing.T) {
 }
 
 func TestSnapshotPreview1_FdWrite_Errors(t *testing.T) {
-	validFD := uint64(3)                                // arbitrary valid fd after 0, 1, and 2, that are stdin/out/err
+	validFD := uint32(3)                                // arbitrary valid fd after 0, 1, and 2, that are stdin/out/err
 	file, memFS := createFile(t, "test_path", []byte{}) // file with empty contents
 	ctx := context.Background()
 	config := NewConfig()
@@ -1464,10 +1462,10 @@ func TestSnapshotPreview1_FdWrite_Errors(t *testing.T) {
 		file:    file,
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionFdWrite, ImportFdWrite, moduleName, config)
+	a, mod, _ := instantiateModule(t, ctx, FunctionFdWrite, ImportFdWrite, moduleName, config)
 
 	// Setup valid test memory
-	iovs, iovsCount := uint64(0), uint64(1)
+	iovs, iovsCount := uint32(0), uint32(1)
 	memory := []byte{
 		8, 0, 0, 0, // = iovs[0].offset (where the data "hi" begins)
 		2, 0, 0, 0, // = iovs[0].length (how many bytes are in "hi")
@@ -1476,7 +1474,7 @@ func TestSnapshotPreview1_FdWrite_Errors(t *testing.T) {
 
 	tests := []struct {
 		name           string
-		fd, resultSize uint64
+		fd, resultSize uint32
 		memory         []byte
 		expectedErrno  wasi.Errno
 	}{
@@ -1513,7 +1511,7 @@ func TestSnapshotPreview1_FdWrite_Errors(t *testing.T) {
 			name:          "resultSize offset is outside memory",
 			fd:            validFD,
 			memory:        memory,
-			resultSize:    uint64(len(memory)), // read was ok, but there wasn't enough memory to write the result.
+			resultSize:    uint32(len(memory)), // read was ok, but there wasn't enough memory to write the result.
 			expectedErrno: wasi.ErrnoFault,
 		},
 	}
@@ -1523,9 +1521,8 @@ func TestSnapshotPreview1_FdWrite_Errors(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			mod.Memory().(*wasm.MemoryInstance).Buffer = tc.memory
 
-			results, err := fn.Call(mod, tc.fd, iovs, iovsCount, tc.resultSize)
-			require.NoError(t, err)
-			require.Equal(t, tc.expectedErrno, wasi.Errno(results[0])) // results[0] is the errno
+			errno := a.FdWrite(mod, tc.fd, iovs, iovsCount, tc.resultSize)
+			require.Equal(t, tc.expectedErrno, errno)
 		})
 	}
 }
@@ -1546,10 +1543,10 @@ func TestSnapshotPreview1_PathCreateDirectory(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionPathCreateDirectory, ImportPathCreateDirectory, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionPathCreateDirectory, ImportPathCreateDirectory, moduleName, config)
 
 	t.Run("SnapshotPreview1.PathCreateDirectory", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PathCreateDirectory(mod, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.PathCreateDirectory(mod, 0, 0, 0))
 	})
 
 	t.Run(FunctionPathCreateDirectory, func(t *testing.T) {
@@ -1564,10 +1561,10 @@ func TestSnapshotPreview1_PathFilestatGet(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionPathFilestatGet, ImportPathFilestatGet, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionPathFilestatGet, ImportPathFilestatGet, moduleName, config)
 
 	t.Run("SnapshotPreview1.PathFilestatGet", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PathFilestatGet(mod, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.PathFilestatGet(mod, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionPathFilestatGet, func(t *testing.T) {
@@ -1582,10 +1579,10 @@ func TestSnapshotPreview1_PathFilestatSetTimes(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionPathFilestatSetTimes, ImportPathFilestatSetTimes, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionPathFilestatSetTimes, ImportPathFilestatSetTimes, moduleName, config)
 
 	t.Run("SnapshotPreview1.PathFilestatSetTimes", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PathFilestatSetTimes(mod, 0, 0, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.PathFilestatSetTimes(mod, 0, 0, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionPathFilestatSetTimes, func(t *testing.T) {
@@ -1600,10 +1597,10 @@ func TestSnapshotPreview1_PathLink(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionPathLink, ImportPathLink, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionPathLink, ImportPathLink, moduleName, config)
 
 	t.Run("SnapshotPreview1.PathLink", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PathLink(mod, 0, 0, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.PathLink(mod, 0, 0, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionPathLink, func(t *testing.T) {
@@ -1645,14 +1642,14 @@ func TestSnapshotPreview1_PathOpen(t *testing.T) {
 
 	ctx := context.Background()
 	config := NewConfig()
+
+	a, mod, fn := instantiateModule(t, ctx, FunctionPathOpen, ImportPathOpen, moduleName, config)
 	// randSource is used to determine the new fd. Fix it to the expectedFD for testing.
-	config.randSource = func(b []byte) error {
+	a.randSource = func(b []byte) error {
 		binary.LittleEndian.PutUint32(b, expectedFD)
 		return nil
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionPathOpen, ImportPathOpen, moduleName, config)
-
 	// TestSnapshotPreview1_PathOpen uses a matrix because setting up test files is complicated and has to be clean each time.
 	type pathOpenFn func(ctx publicwasm.Module, fd, dirflags, path, pathLen, oflags uint32,
 		fsRightsBase, fsRightsInheriting uint64,
@@ -1662,7 +1659,7 @@ func TestSnapshotPreview1_PathOpen(t *testing.T) {
 		pathOpen func() pathOpenFn
 	}{
 		{"SnapshotPreview1.PathOpen", func() pathOpenFn {
-			return NewAPI(config).PathOpen
+			return a.PathOpen
 		}},
 		{FunctionPathOpen, func() pathOpenFn {
 			return func(ctx publicwasm.Module, fd, dirflags, path, pathLen, oflags uint32,
@@ -1719,7 +1716,7 @@ func TestSnapshotPreview1_PathOpen(t *testing.T) {
 }
 
 func TestSnapshotPreview1_PathOpen_Errors(t *testing.T) {
-	validFD := uint64(3) // arbitrary valid fd after 0, 1, and 2, that are stdin/out/err
+	validFD := uint32(3) // arbitrary valid fd after 0, 1, and 2, that are stdin/out/err
 	// Create a memFS for testing that has "./wazero" file.
 	memFS := &MemFS{
 		Files: map[string][]byte{
@@ -1729,23 +1726,23 @@ func TestSnapshotPreview1_PathOpen_Errors(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 	config.opened = map[uint32]fileEntry{
-		uint32(validFD): {
+		validFD: {
 			path:    ".",
 			fileSys: memFS,
 		},
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionPathOpen, ImportPathOpen, moduleName, config)
+	a, mod, _ := instantiateModule(t, ctx, FunctionPathOpen, ImportPathOpen, moduleName, config)
 
-	validPath := uint64(0)    // arbitrary offset
-	validPathLen := uint64(6) // the length of "wazero"
+	validPath := uint32(0)    // arbitrary offset
+	validPathLen := uint32(6) // the length of "wazero"
 	mod.Memory().Write(uint32(validPath), []byte{
 		'w', 'a', 'z', 'e', 'r', 'o', // write to offset 0 (= validPath)
 	}) // wazero is the path to the file in the memFS
 
 	tests := []struct {
 		name                                      string
-		fd, path, pathLen, oflags, resultOpenedFd uint64
+		fd, path, pathLen, oflags, resultOpenedFd uint32
 		expectedErrno                             wasi.Errno
 	}{
 		{
@@ -1756,7 +1753,7 @@ func TestSnapshotPreview1_PathOpen_Errors(t *testing.T) {
 		{
 			name:          "out-of-memory reading path",
 			fd:            validFD,
-			path:          uint64(mod.Memory().Size()),
+			path:          mod.Memory().Size(),
 			pathLen:       validPathLen,
 			expectedErrno: wasi.ErrnoFault,
 		},
@@ -1764,7 +1761,7 @@ func TestSnapshotPreview1_PathOpen_Errors(t *testing.T) {
 			name:          "out-of-memory reading pathLen",
 			fd:            validFD,
 			path:          validPath,
-			pathLen:       uint64(mod.Memory().Size() + 1), // path is in the valid memory range, but pathLen is out-of-memory for path
+			pathLen:       mod.Memory().Size() + 1, // path is in the valid memory range, but pathLen is out-of-memory for path
 			expectedErrno: wasi.ErrnoFault,
 		},
 		{
@@ -1779,7 +1776,7 @@ func TestSnapshotPreview1_PathOpen_Errors(t *testing.T) {
 			fd:             validFD,
 			path:           validPath,
 			pathLen:        validPathLen,
-			resultOpenedFd: uint64(mod.Memory().Size()), // path and pathLen correctly point to the right path, but where to write the opened FD is outside memory.
+			resultOpenedFd: mod.Memory().Size(), // path and pathLen correctly point to the right path, but where to write the opened FD is outside memory.
 			expectedErrno:  wasi.ErrnoFault,
 		},
 	}
@@ -1787,9 +1784,8 @@ func TestSnapshotPreview1_PathOpen_Errors(t *testing.T) {
 	for _, tt := range tests {
 		tc := tt
 		t.Run(tc.name, func(t *testing.T) {
-			results, err := fn.Call(mod, tc.fd, 0, tc.path, tc.pathLen, tc.oflags, 0, 0, 0, tc.resultOpenedFd)
-			require.NoError(t, err)
-			require.Equal(t, tc.expectedErrno, wasi.Errno(results[0])) // results[0] is the errno
+			errno := a.PathOpen(mod, tc.fd, 0, tc.path, tc.pathLen, tc.oflags, 0, 0, 0, tc.resultOpenedFd)
+			require.Equal(t, tc.expectedErrno, errno)
 		})
 	}
 }
@@ -1799,10 +1795,10 @@ func TestSnapshotPreview1_PathReadlink(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionPathReadlink, ImportPathReadlink, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionPathReadlink, ImportPathReadlink, moduleName, config)
 
 	t.Run("SnapshotPreview1.PathLink", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PathReadlink(mod, 0, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.PathReadlink(mod, 0, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionPathReadlink, func(t *testing.T) {
@@ -1817,10 +1813,10 @@ func TestSnapshotPreview1_PathRemoveDirectory(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionPathRemoveDirectory, ImportPathRemoveDirectory, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionPathRemoveDirectory, ImportPathRemoveDirectory, moduleName, config)
 
 	t.Run("SnapshotPreview1.PathRemoveDirectory", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PathRemoveDirectory(mod, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.PathRemoveDirectory(mod, 0, 0, 0))
 	})
 
 	t.Run(FunctionPathRemoveDirectory, func(t *testing.T) {
@@ -1835,10 +1831,10 @@ func TestSnapshotPreview1_PathRename(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionPathRename, ImportPathRename, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionPathRename, ImportPathRename, moduleName, config)
 
 	t.Run("SnapshotPreview1.PathRename", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PathRename(mod, 0, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.PathRename(mod, 0, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionPathRename, func(t *testing.T) {
@@ -1853,10 +1849,10 @@ func TestSnapshotPreview1_PathSymlink(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionPathSymlink, ImportPathSymlink, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionPathSymlink, ImportPathSymlink, moduleName, config)
 
 	t.Run("SnapshotPreview1.PathSymlink", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PathSymlink(mod, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.PathSymlink(mod, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionPathSymlink, func(t *testing.T) {
@@ -1871,10 +1867,10 @@ func TestSnapshotPreview1_PathUnlinkFile(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionPathUnlinkFile, ImportPathUnlinkFile, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionPathUnlinkFile, ImportPathUnlinkFile, moduleName, config)
 
 	t.Run("SnapshotPreview1.PathUnlinkFile", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PathUnlinkFile(mod, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.PathUnlinkFile(mod, 0, 0, 0))
 	})
 
 	t.Run(FunctionPathUnlinkFile, func(t *testing.T) {
@@ -1889,10 +1885,10 @@ func TestSnapshotPreview1_PollOneoff(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionPollOneoff, ImportPollOneoff, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionPollOneoff, ImportPollOneoff, moduleName, config)
 
 	t.Run("SnapshotPreview1.PollOneoff", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).PollOneoff(mod, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.PollOneoff(mod, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionPollOneoff, func(t *testing.T) {
@@ -1921,7 +1917,9 @@ func TestSnapshotPreview1_ProcExit(t *testing.T) {
 		},
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionProcExit, ImportProcExit, moduleName, config)
+	// Note: Unlike most tests, this uses fn, not the 'a' result parameter. This is because currently, this function
+	// body panics, and we expect Call to unwrap the panic.
+	_, mod, fn := instantiateModule(t, ctx, FunctionProcExit, ImportProcExit, moduleName, config)
 
 	for _, tt := range tests {
 		tc := tt
@@ -1941,10 +1939,10 @@ func TestSnapshotPreview1_ProcRaise(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionProcRaise, ImportProcRaise, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionProcRaise, ImportProcRaise, moduleName, config)
 
 	t.Run("SnapshotPreview1.ProcRaise", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).ProcRaise(mod, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.ProcRaise(mod, 0))
 	})
 
 	t.Run(FunctionProcRaise, func(t *testing.T) {
@@ -1959,10 +1957,10 @@ func TestSnapshotPreview1_SchedYield(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionSchedYield, ImportSchedYield, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionSchedYield, ImportSchedYield, moduleName, config)
 
 	t.Run("SnapshotPreview1.SchedYield", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).SchedYield(mod))
+		require.Equal(t, wasi.ErrnoNosys, a.SchedYield(mod))
 	})
 
 	t.Run(FunctionSchedYield, func(t *testing.T) {
@@ -1984,7 +1982,9 @@ func TestSnapshotPreview1_RandomGet(t *testing.T) {
 	seed := int64(42)   // and seed value
 	ctx := context.Background()
 	config := NewConfig()
-	config.randSource = func(p []byte) error {
+
+	a, mod, fn := instantiateModule(t, ctx, FunctionRandomGet, ImportRandomGet, moduleName, config)
+	a.randSource = func(p []byte) error {
 		s := rand.NewSource(seed)
 		rng := rand.New(s)
 		_, err := rng.Read(p)
@@ -1992,13 +1992,11 @@ func TestSnapshotPreview1_RandomGet(t *testing.T) {
 		return err
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionRandomGet, ImportRandomGet, moduleName, config)
-
 	t.Run("SnapshotPreview1.RandomGet", func(t *testing.T) {
 		maskMemory(t, mod, len(expectedMemory))
 
 		// Invoke RandomGet directly and check the memory side effects!
-		errno := NewAPI(config).RandomGet(mod, offset, length)
+		errno := a.RandomGet(mod, offset, length)
 		require.Equal(t, wasi.ErrnoSuccess, errno)
 
 		actual, ok := mod.Memory().Read(0, offset+length+1)
@@ -2025,7 +2023,7 @@ func TestSnapshotPreview1_RandomGet_Errors(t *testing.T) {
 
 	validAddress := uint32(0) // arbitrary valid address
 
-	mod, fn := instantiateModule(t, ctx, FunctionRandomGet, ImportRandomGet, moduleName, config)
+	a, mod, _ := instantiateModule(t, ctx, FunctionRandomGet, ImportRandomGet, moduleName, config)
 	memorySize := mod.Memory().Size()
 
 	tests := []struct {
@@ -2050,9 +2048,8 @@ func TestSnapshotPreview1_RandomGet_Errors(t *testing.T) {
 		tc := tt
 
 		t.Run(tc.name, func(t *testing.T) {
-			results, err := fn.Call(mod, uint64(tc.offset), uint64(tc.length))
-			require.NoError(t, err)
-			require.Equal(t, uint64(wasi.ErrnoFault), results[0]) // results[0] is the errno
+			errno := a.RandomGet(mod, tc.offset, tc.length)
+			require.Equal(t, wasi.ErrnoFault, errno)
 		})
 	}
 }
@@ -2060,15 +2057,14 @@ func TestSnapshotPreview1_RandomGet_Errors(t *testing.T) {
 func TestSnapshotPreview1_RandomGet_SourceError(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
-	config.randSource = func(p []byte) error {
+
+	a, mod, _ := instantiateModule(t, ctx, FunctionRandomGet, ImportRandomGet, moduleName, config)
+	a.randSource = func(p []byte) error {
 		return errors.New("random source error")
 	}
 
-	mod, fn := instantiateModule(t, ctx, FunctionRandomGet, ImportRandomGet, moduleName, config)
-
-	results, err := fn.Call(mod, uint64(1), uint64(5)) // arbitrary offset and length
-	require.NoError(t, err)
-	require.Equal(t, uint64(wasi.ErrnoIo), results[0]) // results[0] is the errno
+	errno := a.RandomGet(mod, uint32(1), uint32(5)) // arbitrary offset and length
+	require.Equal(t, wasi.ErrnoIo, errno)
 }
 
 // TestSnapshotPreview1_SockRecv only tests it is stubbed for GrainLang per #271
@@ -2076,10 +2072,10 @@ func TestSnapshotPreview1_SockRecv(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionSockRecv, ImportSockRecv, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionSockRecv, ImportSockRecv, moduleName, config)
 
 	t.Run("SnapshotPreview1.SockRecv", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).SockRecv(mod, 0, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.SockRecv(mod, 0, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionSockRecv, func(t *testing.T) {
@@ -2094,10 +2090,10 @@ func TestSnapshotPreview1_SockSend(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionSockSend, ImportSockSend, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionSockSend, ImportSockSend, moduleName, config)
 
 	t.Run("SnapshotPreview1.SockSend", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).SockSend(mod, 0, 0, 0, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.SockSend(mod, 0, 0, 0, 0, 0))
 	})
 
 	t.Run(FunctionSockSend, func(t *testing.T) {
@@ -2112,10 +2108,10 @@ func TestSnapshotPreview1_SockShutdown(t *testing.T) {
 	ctx := context.Background()
 	config := NewConfig()
 
-	mod, fn := instantiateModule(t, ctx, FunctionSockShutdown, ImportSockShutdown, moduleName, config)
+	a, mod, fn := instantiateModule(t, ctx, FunctionSockShutdown, ImportSockShutdown, moduleName, config)
 
 	t.Run("SnapshotPreview1.SockShutdown", func(t *testing.T) {
-		require.Equal(t, wasi.ErrnoNosys, NewAPI(config).SockShutdown(mod, 0, 0))
+		require.Equal(t, wasi.ErrnoNosys, a.SockShutdown(mod, 0, 0))
 	})
 
 	t.Run(FunctionSockShutdown, func(t *testing.T) {
@@ -2127,13 +2123,14 @@ func TestSnapshotPreview1_SockShutdown(t *testing.T) {
 
 const testMemoryPageSize = 1
 
-func instantiateModule(t *testing.T, ctx context.Context, wasiFunction, wasiImport, moduleName string, config *Config) (*wasm.ModuleContext, publicwasm.Function) {
+func instantiateModule(t *testing.T, ctx context.Context, wasiFunction, wasiImport, moduleName string, config *Config) (*wasiAPI, *wasm.ModuleContext, publicwasm.Function) {
 	enabledFeatures := wasm.Features20191205
 	store := wasm.NewStore(interpreter.NewEngine(), enabledFeatures)
 
 	// The package `wazero` has a simpler interface for adding host modules, but we can't use that as it would create an
 	// import cycle. Instead, we export internalwasm.NewHostModule and use it here.
-	m, err := wasm.NewHostModule(wasi.ModuleSnapshotPreview1, SnapshotPreview1Functions(config))
+	a, fns := SnapshotPreview1Functions(config)
+	m, err := wasm.NewHostModule(wasi.ModuleSnapshotPreview1, fns)
 	require.NoError(t, err)
 
 	// Double-check what we created passes same validity as module-defined modules.
@@ -2155,7 +2152,7 @@ func instantiateModule(t *testing.T, ctx context.Context, wasiFunction, wasiImpo
 
 	fn := mod.ExportedFunction(wasiFunction)
 	require.NotNil(t, fn)
-	return mod, fn
+	return a, mod, fn
 }
 
 // maskMemory sets the first memory in the store to '?' * size, so tests can see what's written.