Repository: tetratelabs/wazero
Pull request #1226 (2023-03-13 05:40:48)

gojs: introduces `--experimental-workdir` CLI arg
When compiled to `GOOS=js`, wasm does not maintain the working directory: it is defined by the host. While not explicitly documented, [os.TestDirFSRootDir](https://github.com/golang/go/blob/master/src/os/os_test.go#L2841) in Go suggests the working directory must be valid to pass (literally the directory holding the file).

This adds an experimental CLI flag that gives the initial working directory. This is experimental because while GOOS=js uses this, current WASI compilers will not, as they maintain working directory in code managed by wasi-libc, or as a convention (e.g. in Zig).

It is not yet known if [wasi-cli](https://github.com/WebAssembly/wasi-cli) will maintain working directory externally or not.

After this change, our GOOS=js implementation is down to less than ten test failures.
```bash
$ wazero run -mount=/:/ --experimental-workdir=$(go env GOROOT)/src/os os.wasm|grep '^--- FAIL'|wc -l
       9
```

See #1222


Patch:
diff --git a/cmd/wazero/wazero.go b/cmd/wazero/wazero.go
index da3c8eba..c0be1f9b 100644
--- a/cmd/wazero/wazero.go
+++ b/cmd/wazero/wazero.go
@@ -123,11 +123,16 @@ func doRun(args []string, stdOut io.Writer, stdErr logging.Writer, exit func(cod
 	flags.Var(&envs, "env", "key=value pair of environment variable to expose to the binary. "+
 		"Can be specified multiple times.")
 
-	var envExport bool
-	flags.BoolVar(&envExport, "env-inherit", false,
+	var envInherit bool
+	flags.BoolVar(&envInherit, "env-inherit", false,
 		"inherits any environment variables from the calling process."+
 			"Variables specified with the <env> flag are appended to the inherited list.")
 
+	var workdir string
+	flags.StringVar(&workdir, "experimental-workdir", "",
+		"inherits the working directory from the calling process."+
+			"Note: This only applies to wasm compiled with `GOARCH=wasm GOOS=js` a.k.a. gojs.")
+
 	var mounts sliceFlag
 	flags.Var(&mounts, "mount",
 		"filesystem path to expose to the binary in the form of <path>[:<wasm path>][:ro]. "+
@@ -173,7 +178,7 @@ func doRun(args []string, stdOut io.Writer, stdErr logging.Writer, exit func(cod
 
 	// Don't use map to preserve order
 	var env []string
-	if envExport {
+	if envInherit {
 		envs = append(os.Environ(), envs...)
 	}
 	for _, e := range envs {
@@ -195,17 +200,19 @@ func doRun(args []string, stdOut io.Writer, stdErr logging.Writer, exit func(cod
 
 	wasmExe := filepath.Base(wasmPath)
 
-	ctx := maybeHostLogging(context.Background(), logging.LogScopes(hostlogging), stdErr)
-
 	var rtc wazero.RuntimeConfig
 	if useInterpreter {
 		rtc = wazero.NewRuntimeConfigInterpreter()
 	} else {
 		rtc = wazero.NewRuntimeConfig()
 	}
+
+	ctx := maybeHostLogging(context.Background(), logging.LogScopes(hostlogging), stdErr)
+
 	if cache := maybeUseCacheDir(cacheDir, stdErr, exit); cache != nil {
 		rtc = rtc.WithCompilationCache(cache)
 	}
+
 	if timeout > 0 {
 		newCtx, cancel := context.WithTimeout(ctx, timeout)
 		ctx = newCtx
@@ -217,6 +224,10 @@ func doRun(args []string, stdOut io.Writer, stdErr logging.Writer, exit func(cod
 		exit(1)
 	}
 
+	if workdir != "" {
+		ctx = gojs.WithWorkdir(ctx, workdir)
+	}
+
 	rt := wazero.NewRuntimeWithConfig(ctx, rtc)
 	defer rt.Close(ctx)
 
diff --git a/experimental/gojs/gojs.go b/experimental/gojs/gojs.go
index 730bc47d..671ae510 100644
--- a/experimental/gojs/gojs.go
+++ b/experimental/gojs/gojs.go
@@ -16,6 +16,7 @@ package gojs
 import (
 	"context"
 	"net/http"
+	"path/filepath"
 
 	"github.com/tetratelabs/wazero"
 	"github.com/tetratelabs/wazero/api"
@@ -106,6 +107,20 @@ func WithRoundTripper(ctx context.Context, rt http.RoundTripper) context.Context
 	return context.WithValue(ctx, RoundTripperKey{}, rt)
 }
 
+// WithWorkdir sets the initial working directory used to Run Wasm. This
+// defaults to root "/".
+//
+// Here's an example that overrides this to "/usr/local/go/src/os".
+//
+//	ctx = gojs.WithWorkdir(ctx, "/usr/local/go/src/os")
+//	err = gojs.Run(ctx, r, compiled, config)
+func WithWorkdir(ctx context.Context, workdir string) context.Context {
+	// Ensure if used on windows, the input path is translated to a POSIX one.
+	workdir = workdir[len(filepath.VolumeName(workdir)):] // trim volume prefix (C:) on Windows
+	workdir = filepath.ToSlash(workdir)                   // convert \ to /
+	return context.WithValue(ctx, WorkdirKey{}, workdir)
+}
+
 // Run instantiates a new module and calls "run" with the given config.
 //
 // # Parameters
diff --git a/internal/gojs/fs.go b/internal/gojs/fs.go
index 41bdbb83..4f545348 100644
--- a/internal/gojs/fs.go
+++ b/internal/gojs/fs.go
@@ -815,7 +815,7 @@ func jsfsInvoke(ctx context.Context, mod api.Module, callback funcWrapper, err e
 // resolvePath is needed when a non-absolute path is given to a function.
 // Unlike other host ABI, GOOS=js maintains the CWD host side.
 func resolvePath(ctx context.Context, path string) string {
-	if len(path) == 0 || path[0] == '/' || path[0] == '.' {
+	if len(path) == 0 || path[0] == '/' {
 		return path // leave alone .. or absolute paths.
 	}
 	return joinPath(getState(ctx).cwd, path)
diff --git a/internal/gojs/goos/goos.go b/internal/gojs/goos/goos.go
index d46d79ab..3f7eb0ac 100644
--- a/internal/gojs/goos/goos.go
+++ b/internal/gojs/goos/goos.go
@@ -233,7 +233,8 @@ func (s *stack) SetResultUint32(i int, v uint32) {
 }
 
 func NewFunc(name string, goFunc Func) *wasm.HostFunc {
-	return util.NewFunc(name, (&stackFunc{name: name, f: goFunc}).Call)
+	sf := &stackFunc{name: name, f: goFunc}
+	return util.NewFunc(name, sf.Call)
 }
 
 type Func func(context.Context, api.Module, Stack)
diff --git a/internal/gojs/state.go b/internal/gojs/state.go
index ae83dc97..17dc9fff 100644
--- a/internal/gojs/state.go
+++ b/internal/gojs/state.go
@@ -10,11 +10,20 @@ import (
 	"github.com/tetratelabs/wazero/internal/gojs/values"
 )
 
+type WorkdirKey struct{}
+
+func getWorkdir(ctx context.Context) string {
+	if wd, ok := ctx.Value(WorkdirKey{}).(string); ok {
+		return wd
+	}
+	return "/"
+}
+
 func NewState(ctx context.Context) *State {
 	return &State{
 		values:                 values.NewValues(),
 		valueGlobal:            newJsGlobal(getRoundTripper(ctx)),
-		cwd:                    "/",
+		cwd:                    getWorkdir(ctx),
 		_nextCallbackTimeoutID: 1,
 		_scheduledTimeouts:     map[uint32]chan bool{},
 	}
diff --git a/internal/wasm/function_definition.go b/internal/wasm/function_definition.go
index bd7b735c..3cf4646e 100644
--- a/internal/wasm/function_definition.go
+++ b/internal/wasm/function_definition.go
@@ -9,7 +9,8 @@ import (
 //
 // Note: Unlike ExportedFunctions, there is no unique constraint on imports.
 func (m *Module) ImportedFunctions() (ret []api.FunctionDefinition) {
-	for _, d := range m.FunctionDefinitionSection {
+	for i := range m.FunctionDefinitionSection {
+		d := &m.FunctionDefinitionSection[i]
 		if d.importDesc != nil {
 			ret = append(ret, d)
 		}
@@ -20,7 +21,8 @@ func (m *Module) ImportedFunctions() (ret []api.FunctionDefinition) {
 // ExportedFunctions returns the definitions of each exported function.
 func (m *Module) ExportedFunctions() map[string]api.FunctionDefinition {
 	ret := map[string]api.FunctionDefinition{}
-	for _, d := range m.FunctionDefinitionSection {
+	for i := range m.FunctionDefinitionSection {
+		d := &m.FunctionDefinitionSection[i]
 		for _, e := range d.exportNames {
 			ret[e] = d
 		}
@@ -49,7 +51,7 @@ func (m *Module) BuildFunctionDefinitions() {
 	}
 
 	importCount := m.ImportFuncCount()
-	m.FunctionDefinitionSection = make([]*FunctionDefinition, 0, importCount+uint32(len(m.FunctionSection)))
+	m.FunctionDefinitionSection = make([]FunctionDefinition, importCount+uint32(len(m.FunctionSection)))
 
 	importFuncIdx := Index(0)
 	for i := range m.ImportSection {
@@ -58,25 +60,25 @@ func (m *Module) BuildFunctionDefinitions() {
 			continue
 		}
 
-		m.FunctionDefinitionSection = append(m.FunctionDefinitionSection, &FunctionDefinition{
-			importDesc: &[2]string{imp.Module, imp.Name},
-			index:      importFuncIdx,
-			funcType:   m.TypeSection[imp.DescFunc],
-		})
+		def := &m.FunctionDefinitionSection[importFuncIdx]
+		def.importDesc = imp
+		def.index = importFuncIdx
+		def.funcType = m.TypeSection[imp.DescFunc]
 		importFuncIdx++
 	}
 
 	for codeIndex, typeIndex := range m.FunctionSection {
 		code := m.CodeSection[codeIndex]
-		m.FunctionDefinitionSection = append(m.FunctionDefinitionSection, &FunctionDefinition{
-			index:    Index(codeIndex) + importCount,
-			funcType: m.TypeSection[typeIndex],
-			goFunc:   code.GoFunc,
-		})
+		idx := importFuncIdx + Index(codeIndex)
+		def := &m.FunctionDefinitionSection[idx]
+		def.index = idx
+		def.funcType = m.TypeSection[typeIndex]
+		def.goFunc = code.GoFunc
 	}
 
 	n, nLen := 0, len(functionNames)
-	for _, d := range m.FunctionDefinitionSection {
+	for i := range m.FunctionDefinitionSection {
+		d := &m.FunctionDefinitionSection[i]
 		// The function name section begins with imports, but can be sparse.
 		// This keeps track of how far in the name section we've searched.
 		funcIdx := d.index
@@ -114,7 +116,7 @@ type FunctionDefinition struct {
 	debugName   string
 	goFunc      interface{}
 	funcType    *FunctionType
-	importDesc  *[2]string
+	importDesc  *Import
 	exportNames []string
 	paramNames  []string
 	resultNames []string
@@ -142,8 +144,9 @@ func (f *FunctionDefinition) DebugName() string {
 
 // Import implements the same method as documented on api.FunctionDefinition.
 func (f *FunctionDefinition) Import() (moduleName, name string, isImport bool) {
-	if importDesc := f.importDesc; importDesc != nil {
-		moduleName, name, isImport = importDesc[0], importDesc[1], true
+	if f.importDesc != nil {
+		importDesc := f.importDesc
+		moduleName, name, isImport = importDesc.Module, importDesc.Name, true
 	}
 	return
 }
diff --git a/internal/wasm/host.go b/internal/wasm/host.go
index 12f91856..15e542b6 100644
--- a/internal/wasm/host.go
+++ b/internal/wasm/host.go
@@ -180,7 +180,7 @@ func addFuncs(
 	m.NameSection.FunctionNames = make([]*NameAssoc, 0, funcCount)
 	m.FunctionSection = make([]Index, 0, funcCount)
 	m.CodeSection = make([]*Code, 0, funcCount)
-	m.FunctionDefinitionSection = make([]*FunctionDefinition, 0, funcCount)
+	m.FunctionDefinitionSection = make([]FunctionDefinition, 0, funcCount)
 
 	idx := Index(0)
 	for _, name := range funcNames {
diff --git a/internal/wasm/memory_definition.go b/internal/wasm/memory_definition.go
index 0f2d0dbc..be497bd7 100644
--- a/internal/wasm/memory_definition.go
+++ b/internal/wasm/memory_definition.go
@@ -4,7 +4,8 @@ import "github.com/tetratelabs/wazero/api"
 
 // ImportedMemories implements the same method as documented on wazero.CompiledModule.
 func (m *Module) ImportedMemories() (ret []api.MemoryDefinition) {
-	for _, d := range m.MemoryDefinitionSection {
+	for i := range m.MemoryDefinitionSection {
+		d := &m.MemoryDefinitionSection[i]
 		if d.importDesc != nil {
 			ret = append(ret, d)
 		}
@@ -15,7 +16,8 @@ func (m *Module) ImportedMemories() (ret []api.MemoryDefinition) {
 // ExportedMemories implements the same method as documented on wazero.CompiledModule.
 func (m *Module) ExportedMemories() map[string]api.MemoryDefinition {
 	ret := map[string]api.MemoryDefinition{}
-	for _, d := range m.MemoryDefinitionSection {
+	for i := range m.MemoryDefinitionSection {
+		d := &m.MemoryDefinitionSection[i]
 		for _, e := range d.exportNames {
 			ret[e] = d
 		}
@@ -42,7 +44,7 @@ func (m *Module) BuildMemoryDefinitions() {
 		return
 	}
 
-	m.MemoryDefinitionSection = make([]*MemoryDefinition, 0, memoryCount)
+	m.MemoryDefinitionSection = make([]MemoryDefinition, 0, memoryCount)
 	importMemIdx := Index(0)
 	for i := range m.ImportSection {
 		imp := &m.ImportSection[i]
@@ -50,7 +52,7 @@ func (m *Module) BuildMemoryDefinitions() {
 			continue
 		}
 
-		m.MemoryDefinitionSection = append(m.MemoryDefinitionSection, &MemoryDefinition{
+		m.MemoryDefinitionSection = append(m.MemoryDefinitionSection, MemoryDefinition{
 			importDesc: &[2]string{imp.Module, imp.Name},
 			index:      importMemIdx,
 			memory:     imp.DescMem,
@@ -59,13 +61,14 @@ func (m *Module) BuildMemoryDefinitions() {
 	}
 
 	if m.MemorySection != nil {
-		m.MemoryDefinitionSection = append(m.MemoryDefinitionSection, &MemoryDefinition{
+		m.MemoryDefinitionSection = append(m.MemoryDefinitionSection, MemoryDefinition{
 			index:  importMemIdx,
 			memory: m.MemorySection,
 		})
 	}
 
-	for _, d := range m.MemoryDefinitionSection {
+	for i := range m.MemoryDefinitionSection {
+		d := &m.MemoryDefinitionSection[i]
 		d.moduleName = moduleName
 		for i := range m.ExportSection {
 			e := &m.ExportSection[i]
diff --git a/internal/wasm/module.go b/internal/wasm/module.go
index 34039658..e19bc71d 100644
--- a/internal/wasm/module.go
+++ b/internal/wasm/module.go
@@ -168,7 +168,7 @@ type Module struct {
 	// consistent initialization result.
 	//
 	// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#table-instances%E2%91%A0
-	validatedActiveElementSegments []*validatedActiveElementSegment
+	validatedActiveElementSegments []validatedActiveElementSegment
 
 	// DataCountSection is the optional section and holds the number of data segments in the data section.
 	//
@@ -184,10 +184,10 @@ type Module struct {
 	IsHostModule bool
 
 	// FunctionDefinitionSection is a wazero-specific section built on Validate.
-	FunctionDefinitionSection []*FunctionDefinition
+	FunctionDefinitionSection []FunctionDefinition
 
 	// MemoryDefinitionSection is a wazero-specific section built on Validate.
-	MemoryDefinitionSection []*MemoryDefinition
+	MemoryDefinitionSection []MemoryDefinition
 
 	// DWARFLines is used to emit DWARF based stack trace. This is created from the multiple custom sections
 	// as described in https://yurydelendik.github.io/webassembly-dwarf/, though it is not specified in the Wasm
@@ -628,7 +628,7 @@ func (m *ModuleInstance) BuildFunctions(mod *Module, importedFunctions []*Functi
 	}
 	for i, section := range mod.FunctionSection {
 		offset := uint32(i) + importCount
-		d := mod.FunctionDefinitionSection[offset]
+		d := &mod.FunctionDefinitionSection[offset]
 		// This object is only referenced from a slice. Instead of creating a heap object
 		// here and storing a pointer, we store the struct directly in the slice. This
 		// reduces the number of heap objects which improves GC performance.
@@ -665,7 +665,7 @@ func (m *Module) buildMemory() (mem *MemoryInstance) {
 	memSec := m.MemorySection
 	if memSec != nil {
 		mem = NewMemoryInstance(memSec)
-		mem.definition = m.MemoryDefinitionSection[0]
+		mem.definition = &m.MemoryDefinitionSection[0]
 	}
 	return
 }
diff --git a/internal/wasm/table.go b/internal/wasm/table.go
index 78d98eaf..e7471710 100644
--- a/internal/wasm/table.go
+++ b/internal/wasm/table.go
@@ -140,7 +140,7 @@ type validatedActiveElementSegment struct {
 
 // validateTable ensures any ElementSegment is valid. This caches results via Module.validatedActiveElementSegments.
 // Note: limitsType are validated by decoders, so not re-validated here.
-func (m *Module) validateTable(enabledFeatures api.CoreFeatures, tables []Table, maximumTableIndex uint32) ([]*validatedActiveElementSegment, error) {
+func (m *Module) validateTable(enabledFeatures api.CoreFeatures, tables []Table, maximumTableIndex uint32) ([]validatedActiveElementSegment, error) {
 	if len(tables) > int(maximumTableIndex) {
 		return nil, fmt.Errorf("too many tables in a module: %d given with limit %d", len(tables), maximumTableIndex)
 	}
@@ -151,7 +151,7 @@ func (m *Module) validateTable(enabledFeatures api.CoreFeatures, tables []Table,
 
 	importedTableCount := m.ImportTableCount()
 
-	ret := make([]*validatedActiveElementSegment, 0, m.SectionElementCount(SectionIDElement))
+	ret := make([]validatedActiveElementSegment, 0, m.SectionElementCount(SectionIDElement))
 
 	// Create bounds checks as these can err prior to instantiation
 	funcCount := m.importCount(ExternTypeFunc) + m.SectionElementCount(SectionIDFunction)
@@ -204,7 +204,7 @@ func (m *Module) validateTable(enabledFeatures api.CoreFeatures, tables []Table,
 					continue // Per https://github.com/WebAssembly/spec/issues/1427 init can be no-op, but validate anyway!
 				}
 
-				ret = append(ret, &validatedActiveElementSegment{opcode: oc, arg: globalIdx, init: elem.Init, tableIndex: elem.TableIndex})
+				ret = append(ret, validatedActiveElementSegment{opcode: oc, arg: globalIdx, init: elem.Init, tableIndex: elem.TableIndex})
 			} else if oc == OpcodeI32Const {
 				// Treat constants as signed as their interpretation is not yet known per /RATIONALE.md
 				o, _, err := leb128.LoadInt32(elem.OffsetExpr.Data)
@@ -226,7 +226,7 @@ func (m *Module) validateTable(enabledFeatures api.CoreFeatures, tables []Table,
 					continue // Per https://github.com/WebAssembly/spec/issues/1427 init can be no-op, but validate anyway!
 				}
 
-				ret = append(ret, &validatedActiveElementSegment{opcode: oc, arg: offset, init: elem.Init, tableIndex: elem.TableIndex})
+				ret = append(ret, validatedActiveElementSegment{opcode: oc, arg: offset, init: elem.Init, tableIndex: elem.TableIndex})
 			} else {
 				return nil, fmt.Errorf("%s[%d] has an invalid const expression: %s", SectionIDName(SectionIDElement), idx, InstructionName(oc))
 			}
@@ -261,7 +261,8 @@ func (m *Module) buildTables(importedTables []*TableInstance, importedGlobals []
 		return
 	}
 
-	for elemI, elem := range elementSegments {
+	for elemI := range elementSegments { // Do not loop over the value since elementSegments is a slice of value.
+		elem := &elementSegments[elemI]
 		table := tables[elem.tableIndex]
 		var offset uint32
 		if elem.opcode == OpcodeGlobalGet {
diff --git a/runtime.go b/runtime.go
index edd4252f..c4a33e76 100644
--- a/runtime.go
+++ b/runtime.go
@@ -231,7 +231,7 @@ func buildListeners(ctx context.Context, internal *wasm.Module) ([]experimentala
 	importCount := internal.ImportFuncCount()
 	listeners := make([]experimentalapi.FunctionListener, len(internal.FunctionSection))
 	for i := 0; i < len(listeners); i++ {
-		listeners[i] = factory.NewListener(internal.FunctionDefinitionSection[uint32(i)+importCount])
+		listeners[i] = factory.NewListener(&internal.FunctionDefinitionSection[uint32(i)+importCount])
 	}
 	return listeners, nil
 }


Test patch:
diff --git a/cmd/wazero/wazero_test.go b/cmd/wazero/wazero_test.go
index 393ecdfd..43440f05 100644
--- a/cmd/wazero/wazero_test.go
+++ b/cmd/wazero/wazero_test.go
@@ -344,6 +344,13 @@ func TestRun(t *testing.T) {
 			wasmArgs:       []string{"/bear.txt"},
 			expectedStdout: "pooh\n",
 		},
+		{
+			name:           "GOARCH=wasm GOOS=js workdir",
+			wasm:           wasmCatGo,
+			wazeroOpts:     []string{"--mount=/:/", fmt.Sprintf("--experimental-workdir=%s", bearDir)},
+			wasmArgs:       []string{"bear.txt"},
+			expectedStdout: "pooh\n",
+		},
 		{
 			name:           "GOARCH=wasm GOOS=js readonly",
 			wasm:           wasmCatGo,
@@ -479,6 +486,10 @@ func TestRun(t *testing.T) {
 	for _, tt := range append(tests, cryptoTest) {
 		tc := tt
 
+		if runtime.GOOS == "windows" && tc.name == "GOARCH=wasm GOOS=js workdir" {
+			continue // TODO: Adrian fix this before next RC
+		}
+
 		if tc.wasm == nil {
 			// We should only skip when the runtime is a scratch image.
 			require.False(t, platform.CompilerSupported())
diff --git a/experimental/logging/log_listener_test.go b/experimental/logging/log_listener_test.go
index 6cd5c117..d0271323 100644
--- a/experimental/logging/log_listener_test.go
+++ b/experimental/logging/log_listener_test.go
@@ -297,7 +297,7 @@ func Test_loggingListener(t *testing.T) {
 				m.CodeSection = []*wasm.Code{{Body: []byte{wasm.OpcodeEnd}}}
 			}
 			m.BuildFunctionDefinitions()
-			def := m.FunctionDefinitionSection[0]
+			def := &m.FunctionDefinitionSection[0]
 			l := lf.NewListener(def)
 
 			out.Reset()
@@ -332,9 +332,9 @@ func Test_loggingListener_indentation(t *testing.T) {
 		},
 	}
 	m.BuildFunctionDefinitions()
-	def1 := m.FunctionDefinitionSection[0]
+	def1 := &m.FunctionDefinitionSection[0]
 	l1 := lf.NewListener(def1)
-	def2 := m.FunctionDefinitionSection[1]
+	def2 := &m.FunctionDefinitionSection[1]
 	l2 := lf.NewListener(def2)
 
 	ctx := l1.Before(testCtx, nil, def1, []uint64{})
diff --git a/internal/gojs/compiler_test.go b/internal/gojs/compiler_test.go
index a2392c7c..dbe5e81d 100644
--- a/internal/gojs/compiler_test.go
+++ b/internal/gojs/compiler_test.go
@@ -141,16 +141,16 @@ func TestMain(m *testing.M) {
 // For example, this allows testing both Go 1.18 and 1.19 in CI.
 func compileJsWasm(goBin string) error {
 	// Prepare the working directory.
-	workDir, err := os.MkdirTemp("", "example")
+	workdir, err := os.MkdirTemp("", "example")
 	if err != nil {
 		return err
 	}
-	defer os.RemoveAll(workDir)
+	defer os.RemoveAll(workdir)
 
 	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
 	defer cancel()
 
-	bin := path.Join(workDir, "out.wasm")
+	bin := path.Join(workdir, "out.wasm")
 	cmd := exec.CommandContext(ctx, goBin, "build", "-o", bin, ".") //nolint:gosec
 	cmd.Env = append(os.Environ(), "GOOS=js", "GOARCH=wasm", "GOWASM=satconv,signext")
 	cmd.Dir = "testdata"
diff --git a/internal/platform/open_file_test.go b/internal/platform/open_file_test.go
index cc6f754a..468c03d3 100644
--- a/internal/platform/open_file_test.go
+++ b/internal/platform/open_file_test.go
@@ -3,12 +3,26 @@ package platform
 import (
 	"os"
 	path "path/filepath"
+	"runtime"
 	"syscall"
 	"testing"
 
 	"github.com/tetratelabs/wazero/internal/testing/require"
 )
 
+func TestOpenFile(t *testing.T) {
+	tmpDir := t.TempDir()
+
+	// from os.TestDirFSPathsValid
+	if runtime.GOOS != "windows" {
+		t.Run("strange name", func(t *testing.T) {
+			f, err := OpenFile(path.Join(tmpDir, `e:xperi\ment.txt`), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
+			require.NoError(t, err)
+			require.NoError(t, f.Close())
+		})
+	}
+}
+
 func TestOpenFile_Errors(t *testing.T) {
 	tmpDir := t.TempDir()
 
diff --git a/internal/sysfs/dirfs_test.go b/internal/sysfs/dirfs_test.go
index 74e07c12..67019698 100644
--- a/internal/sysfs/dirfs_test.go
+++ b/internal/sysfs/dirfs_test.go
@@ -690,6 +690,17 @@ func TestDirFS_Stat(t *testing.T) {
 
 	testFS := NewDirFS(tmpDir)
 	testStat(t, testFS)
+
+	// from os.TestDirFSPathsValid
+	if runtime.GOOS != "windows" {
+		t.Run("strange name", func(t *testing.T) {
+			name := `e:xperi\ment.txt`
+			require.NoError(t, os.WriteFile(path.Join(tmpDir, name), nil, 0o600))
+
+			var st platform.Stat_t
+			require.NoError(t, testFS.Stat(name, &st))
+		})
+	}
 }
 
 func TestDirFS_Truncate(t *testing.T) {
diff --git a/internal/sysfs/dirfs_unix_test.go b/internal/sysfs/dirfs_unix_test.go
index f08df51c..2cc7ef97 100644
--- a/internal/sysfs/dirfs_unix_test.go
+++ b/internal/sysfs/dirfs_unix_test.go
@@ -1,4 +1,4 @@
-//go:build unix
+//go:build !windows
 
 package sysfs
 
diff --git a/internal/sysfs/sysfs_test.go b/internal/sysfs/sysfs_test.go
index 279f5fba..c1bc5e9b 100644
--- a/internal/sysfs/sysfs_test.go
+++ b/internal/sysfs/sysfs_test.go
@@ -63,6 +63,18 @@ func testOpen_O_RDWR(t *testing.T, tmpDir string, testFS FS) {
 	stat, err := f.Stat()
 	require.NoError(t, err)
 	require.Equal(t, fs.FileMode(0o444), stat.Mode().Perm())
+
+	// from os.TestDirFSPathsValid
+	if runtime.GOOS != "windows" {
+		t.Run("strange name", func(t *testing.T) {
+			f, err := testFS.OpenFile(`e:xperi\ment.txt`, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
+			require.NoError(t, err)
+			defer f.Close()
+
+			var st platform.Stat_t
+			require.NoError(t, platform.StatFile(f, &st))
+		})
+	}
 }
 
 func testOpen_Read(t *testing.T, testFS FS, expectIno bool) {
diff --git a/internal/testing/enginetest/enginetest.go b/internal/testing/enginetest/enginetest.go
index a54f2dee..83e8c84a 100644
--- a/internal/testing/enginetest/enginetest.go
+++ b/internal/testing/enginetest/enginetest.go
@@ -843,7 +843,7 @@ func buildListeners(factory experimental.FunctionListenerFactory, m *wasm.Module
 	listeners := make([]experimental.FunctionListener, len(m.FunctionSection))
 	importCount := m.ImportFuncCount()
 	for i := 0; i < len(listeners); i++ {
-		listeners[i] = factory.NewListener(m.FunctionDefinitionSection[uint32(i)+importCount])
+		listeners[i] = factory.NewListener(&m.FunctionDefinitionSection[uint32(i)+importCount])
 	}
 	return listeners
 }
diff --git a/internal/wasm/function_definition_test.go b/internal/wasm/function_definition_test.go
index d8fcb945..04456083 100644
--- a/internal/wasm/function_definition_test.go
+++ b/internal/wasm/function_definition_test.go
@@ -8,12 +8,17 @@ import (
 )
 
 func TestModule_BuildFunctionDefinitions(t *testing.T) {
+	imp := &Import{
+		Type:     ExternTypeFunc,
+		DescFunc: 2, // Index of type.
+	}
+
 	nopCode := &Code{Body: []byte{OpcodeEnd}}
 	fn := func(uint32) uint32 { return 1 }
 	tests := []struct {
 		name            string
 		m               *Module
-		expected        []*FunctionDefinition
+		expected        []FunctionDefinition
 		expectedImports []api.FunctionDefinition
 		expectedExports map[string]api.FunctionDefinition
 	}{
@@ -43,7 +48,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
 					ResultNames:   IndirectNameMap{{Index: Index(0), NameMap: NameMap{{Index: Index(0), Name: "y"}}}},
 				},
 			},
-			expected: []*FunctionDefinition{
+			expected: []FunctionDefinition{
 				{
 					index:       0,
 					name:        "fn",
@@ -79,7 +84,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
 					{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
 				},
 			},
-			expected: []*FunctionDefinition{
+			expected: []FunctionDefinition{
 				{
 					index:       0,
 					debugName:   ".$0",
@@ -123,10 +128,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
 		{
 			name: "with imports",
 			m: &Module{
-				ImportSection: []Import{{
-					Type:     ExternTypeFunc,
-					DescFunc: 2, // Index of type.
-				}},
+				ImportSection: []Import{*imp},
 				ExportSection: []Export{
 					{Name: "imported_function", Type: ExternTypeFunc, Index: 0},
 					{Name: "function_index=1", Type: ExternTypeFunc, Index: 1},
@@ -140,11 +142,11 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
 					{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
 				},
 			},
-			expected: []*FunctionDefinition{
+			expected: []FunctionDefinition{
 				{
 					index:       0,
 					debugName:   ".$0",
-					importDesc:  &[2]string{"", ""},
+					importDesc:  imp,
 					exportNames: []string{"imported_function"},
 					funcType:    &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
 				},
@@ -165,7 +167,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
 				&FunctionDefinition{
 					index:       0,
 					debugName:   ".$0",
-					importDesc:  &[2]string{"", ""},
+					importDesc:  imp,
 					exportNames: []string{"imported_function"},
 					funcType:    &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
 				},
@@ -174,7 +176,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
 				"imported_function": &FunctionDefinition{
 					index:       0,
 					debugName:   ".$0",
-					importDesc:  &[2]string{"", ""},
+					importDesc:  imp,
 					exportNames: []string{"imported_function"},
 					funcType:    &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
 				},
@@ -208,8 +210,8 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
 				FunctionSection: []Index{0, 0, 0, 0, 0},
 				CodeSection:     []*Code{nopCode, nopCode, nopCode, nopCode, nopCode},
 			},
-			expected: []*FunctionDefinition{
-				{moduleName: "module", index: 0, debugName: "module.$0", importDesc: &[2]string{"i", "f"}, funcType: v_v},
+			expected: []FunctionDefinition{
+				{moduleName: "module", index: 0, debugName: "module.$0", importDesc: &Import{Module: "i", Name: "f"}, funcType: v_v},
 				{moduleName: "module", index: 1, debugName: "module.$1", funcType: v_v},
 				{moduleName: "module", index: 2, debugName: "module.two", funcType: v_v, name: "two"},
 				{moduleName: "module", index: 3, debugName: "module.$3", funcType: v_v},
@@ -217,7 +219,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
 				{moduleName: "module", index: 5, debugName: "module.five", funcType: v_v, name: "five"},
 			},
 			expectedImports: []api.FunctionDefinition{
-				&FunctionDefinition{moduleName: "module", index: 0, debugName: "module.$0", importDesc: &[2]string{"i", "f"}, funcType: v_v},
+				&FunctionDefinition{moduleName: "module", index: 0, debugName: "module.$0", importDesc: &Import{Module: "i", Name: "f"}, funcType: v_v},
 			},
 			expectedExports: map[string]api.FunctionDefinition{},
 		},
diff --git a/internal/wasm/memory_definition_test.go b/internal/wasm/memory_definition_test.go
index f6dc4f4e..38daeb11 100644
--- a/internal/wasm/memory_definition_test.go
+++ b/internal/wasm/memory_definition_test.go
@@ -11,7 +11,7 @@ func TestModule_BuildMemoryDefinitions(t *testing.T) {
 	tests := []struct {
 		name            string
 		m               *Module
-		expected        []*MemoryDefinition
+		expected        []MemoryDefinition
 		expectedImports []api.MemoryDefinition
 		expectedExports map[string]api.MemoryDefinition
 	}{
@@ -31,7 +31,7 @@ func TestModule_BuildMemoryDefinitions(t *testing.T) {
 		{
 			name:            "defines memory{0,}",
 			m:               &Module{MemorySection: &Memory{Min: 0}},
-			expected:        []*MemoryDefinition{{index: 0, memory: &Memory{Min: 0}}},
+			expected:        []MemoryDefinition{{index: 0, memory: &Memory{Min: 0}}},
 			expectedExports: map[string]api.MemoryDefinition{},
 		},
 		{
@@ -44,7 +44,7 @@ func TestModule_BuildMemoryDefinitions(t *testing.T) {
 				GlobalSection: []Global{{}},
 				MemorySection: &Memory{Min: 2, Max: 3, IsMaxEncoded: true},
 			},
-			expected: []*MemoryDefinition{
+			expected: []MemoryDefinition{
 				{
 					index:       0,
 					exportNames: []string{"memory_index=0"},
@@ -72,7 +72,7 @@ func TestModule_BuildMemoryDefinitions(t *testing.T) {
 				},
 				MemorySection: &Memory{Min: 2, Max: 3, IsMaxEncoded: true},
 			},
-			expected: []*MemoryDefinition{
+			expected: []MemoryDefinition{
 				{
 					index:       0,
 					importDesc:  &[2]string{"", ""},
diff --git a/internal/wasm/module_test.go b/internal/wasm/module_test.go
index a65787a9..3b1f2282 100644
--- a/internal/wasm/module_test.go
+++ b/internal/wasm/module_test.go
@@ -815,7 +815,7 @@ func TestModule_buildFunctions(t *testing.T) {
 		ImportSection:   []Import{{Type: ExternTypeFunc}},
 		FunctionSection: []Index{0, 0, 0, 0, 0},
 		CodeSection:     []*Code{nopCode, nopCode, nopCode, nopCode, nopCode},
-		FunctionDefinitionSection: []*FunctionDefinition{
+		FunctionDefinitionSection: []FunctionDefinition{
 			{index: 0, funcType: v_v},
 			{index: 1, funcType: v_v},
 			{index: 2, funcType: v_v, name: "two"},
@@ -842,15 +842,15 @@ func TestModule_buildMemoryInstance(t *testing.T) {
 	t.Run("non-nil", func(t *testing.T) {
 		min := uint32(1)
 		max := uint32(10)
-		mDef := &MemoryDefinition{moduleName: "foo"}
+		mDef := MemoryDefinition{moduleName: "foo"}
 		m := Module{
 			MemorySection:           &Memory{Min: min, Cap: min, Max: max},
-			MemoryDefinitionSection: []*MemoryDefinition{mDef},
+			MemoryDefinitionSection: []MemoryDefinition{mDef},
 		}
 		mem := m.buildMemory()
 		require.Equal(t, min, mem.Min)
 		require.Equal(t, max, mem.Max)
-		require.Equal(t, mDef, mem.definition)
+		require.Equal(t, &mDef, mem.definition)
 	})
 }
 
diff --git a/internal/wasm/store_test.go b/internal/wasm/store_test.go
index ca669412..da90c4d0 100644
--- a/internal/wasm/store_test.go
+++ b/internal/wasm/store_test.go
@@ -32,14 +32,14 @@ func TestModuleInstance_Memory(t *testing.T) {
 			name: "memory not exported, one page",
 			input: &Module{
 				MemorySection:           &Memory{Min: 1, Cap: 1},
-				MemoryDefinitionSection: []*MemoryDefinition{{}},
+				MemoryDefinitionSection: []MemoryDefinition{{}},
 			},
 		},
 		{
 			name: "memory exported, different name",
 			input: &Module{
 				MemorySection:           &Memory{Min: 1, Cap: 1},
-				MemoryDefinitionSection: []*MemoryDefinition{{}},
+				MemoryDefinitionSection: []MemoryDefinition{{}},
 				ExportSection:           []Export{{Type: ExternTypeMemory, Name: "momory", Index: 0}},
 			},
 		},
@@ -47,7 +47,7 @@ func TestModuleInstance_Memory(t *testing.T) {
 			name: "memory exported, but zero length",
 			input: &Module{
 				MemorySection:           &Memory{},
-				MemoryDefinitionSection: []*MemoryDefinition{{}},
+				MemoryDefinitionSection: []MemoryDefinition{{}},
 				ExportSection:           []Export{{Type: ExternTypeMemory, Name: "memory", Index: 0}},
 			},
 			expected: true,
@@ -56,7 +56,7 @@ func TestModuleInstance_Memory(t *testing.T) {
 			name: "memory exported, one page",
 			input: &Module{
 				MemorySection:           &Memory{Min: 1, Cap: 1},
-				MemoryDefinitionSection: []*MemoryDefinition{{}},
+				MemoryDefinitionSection: []MemoryDefinition{{}},
 				ExportSection:           []Export{{Type: ExternTypeMemory, Name: "memory", Index: 0}},
 			},
 			expected:    true,
@@ -66,7 +66,7 @@ func TestModuleInstance_Memory(t *testing.T) {
 			name: "memory exported, two pages",
 			input: &Module{
 				MemorySection:           &Memory{Min: 2, Cap: 2},
-				MemoryDefinitionSection: []*MemoryDefinition{{}},
+				MemoryDefinitionSection: []MemoryDefinition{{}},
 				ExportSection:           []Export{{Type: ExternTypeMemory, Name: "memory", Index: 0}},
 			},
 			expected:    true,
@@ -149,7 +149,7 @@ func TestStore_CloseWithExitCode(t *testing.T) {
 				FunctionSection:           []uint32{0},
 				CodeSection:               []*Code{{Body: []byte{OpcodeEnd}}},
 				ExportSection:             []Export{{Type: ExternTypeFunc, Index: 0, Name: "fn"}},
-				FunctionDefinitionSection: []*FunctionDefinition{{funcType: v_v}},
+				FunctionDefinitionSection: []FunctionDefinition{{funcType: v_v}},
 			}, importedModuleName, nil, []FunctionTypeID{0})
 			require.NoError(t, err)
 
@@ -157,7 +157,7 @@ func TestStore_CloseWithExitCode(t *testing.T) {
 				TypeSection:             []*FunctionType{v_v},
 				ImportSection:           []Import{{Type: ExternTypeFunc, Module: importedModuleName, Name: "fn", DescFunc: 0}},
 				MemorySection:           &Memory{Min: 1, Cap: 1},
-				MemoryDefinitionSection: []*MemoryDefinition{{}},
+				MemoryDefinitionSection: []MemoryDefinition{{}},
 				GlobalSection:           []Global{{Type: GlobalType{}, Init: ConstantExpression{Opcode: OpcodeI32Const, Data: const1}}},
 				TableSection:            []Table{{Min: 10}},
 			}, importingModuleName, nil, []FunctionTypeID{0})
@@ -198,7 +198,7 @@ func TestStore_hammer(t *testing.T) {
 		FunctionSection:         []uint32{0},
 		CodeSection:             []*Code{{Body: []byte{OpcodeEnd}}},
 		MemorySection:           &Memory{Min: 1, Cap: 1},
-		MemoryDefinitionSection: []*MemoryDefinition{{}},
+		MemoryDefinitionSection: []MemoryDefinition{{}},
 		GlobalSection: []Global{{
 			Type: GlobalType{ValType: ValueTypeI32},
 			Init: ConstantExpression{Opcode: OpcodeI32Const, Data: leb128.EncodeInt32(1)},
@@ -252,7 +252,7 @@ func TestStore_hammer_close(t *testing.T) {
 		FunctionSection:         []uint32{0},
 		CodeSection:             []*Code{{Body: []byte{OpcodeEnd}}},
 		MemorySection:           &Memory{Min: 1, Cap: 1},
-		MemoryDefinitionSection: []*MemoryDefinition{{}},
+		MemoryDefinitionSection: []MemoryDefinition{{}},
 		GlobalSection: []Global{{
 			Type: GlobalType{ValType: ValueTypeI32},
 			Init: ConstantExpression{Opcode: OpcodeI32Const, Data: leb128.EncodeInt32(1)},
diff --git a/internal/wasm/table_test.go b/internal/wasm/table_test.go
index 8c6352c1..171e2569 100644
--- a/internal/wasm/table_test.go
+++ b/internal/wasm/table_test.go
@@ -67,27 +67,27 @@ func TestModule_validateTable(t *testing.T) {
 	tests := []struct {
 		name     string
 		input    *Module
-		expected []*validatedActiveElementSegment
+		expected []validatedActiveElementSegment
 	}{
 		{
 			name:     "empty",
 			input:    &Module{},
-			expected: []*validatedActiveElementSegment{},
+			expected: []validatedActiveElementSegment{},
 		},
 		{
 			name:     "min zero",
 			input:    &Module{TableSection: []Table{{}}},
-			expected: []*validatedActiveElementSegment{},
+			expected: []validatedActiveElementSegment{},
 		},
 		{
 			name:     "maximum number of tables",
 			input:    &Module{TableSection: []Table{{}, {}, {}, {}, {}}},
-			expected: []*validatedActiveElementSegment{},
+			expected: []validatedActiveElementSegment{},
 		},
 		{
 			name:     "min/max",
 			input:    &Module{TableSection: []Table{{Min: 1, Max: &three}}},
-			expected: []*validatedActiveElementSegment{},
+			expected: []validatedActiveElementSegment{},
 		},
 		{ // See: https://github.com/WebAssembly/spec/issues/1427
 			name: "constant derived element offset=0 and no index",
@@ -103,7 +103,7 @@ func TestModule_validateTable(t *testing.T) {
 					},
 				},
 			},
-			expected: []*validatedActiveElementSegment{},
+			expected: []validatedActiveElementSegment{},
 		},
 		{
 			name: "constant derived element offset=0 and one index",
@@ -120,7 +120,7 @@ func TestModule_validateTable(t *testing.T) {
 					},
 				},
 			},
-			expected: []*validatedActiveElementSegment{
+			expected: []validatedActiveElementSegment{
 				{opcode: OpcodeI32Const, arg: 0, init: []*Index{uint32Ptr(0)}},
 			},
 		},
@@ -139,7 +139,7 @@ func TestModule_validateTable(t *testing.T) {
 					},
 				},
 			},
-			expected: []*validatedActiveElementSegment{
+			expected: []validatedActiveElementSegment{
 				{opcode: OpcodeI32Const, arg: 0, init: []*Index{uint32Ptr(0)}},
 			},
 		},
@@ -158,7 +158,7 @@ func TestModule_validateTable(t *testing.T) {
 					},
 				},
 			},
-			expected: []*validatedActiveElementSegment{
+			expected: []validatedActiveElementSegment{
 				{opcode: OpcodeI32Const, arg: 0, init: []*Index{uint32Ptr(0)}},
 			},
 		},
@@ -177,7 +177,7 @@ func TestModule_validateTable(t *testing.T) {
 					},
 				},
 			},
-			expected: []*validatedActiveElementSegment{
+			expected: []validatedActiveElementSegment{
 				{opcode: OpcodeI32Const, arg: 1, init: []*Index{uint32Ptr(0), uint32Ptr(2)}},
 			},
 		},
@@ -198,7 +198,7 @@ func TestModule_validateTable(t *testing.T) {
 					},
 				},
 			},
-			expected: []*validatedActiveElementSegment{},
+			expected: []validatedActiveElementSegment{},
 		},
 		{
 			name: "imported global derived element offset and one index",
@@ -218,7 +218,7 @@ func TestModule_validateTable(t *testing.T) {
 					},
 				},
 			},
-			expected: []*validatedActiveElementSegment{
+			expected: []validatedActiveElementSegment{
 				{opcode: OpcodeGlobalGet, arg: 0, init: []*Index{uint32Ptr(0)}},
 			},
 		},
@@ -240,7 +240,7 @@ func TestModule_validateTable(t *testing.T) {
 					},
 				},
 			},
-			expected: []*validatedActiveElementSegment{
+			expected: []validatedActiveElementSegment{
 				{opcode: OpcodeGlobalGet, arg: 0, init: []*Index{uint32Ptr(0)}},
 			},
 		},
@@ -262,7 +262,7 @@ func TestModule_validateTable(t *testing.T) {
 					},
 				},
 			},
-			expected: []*validatedActiveElementSegment{
+			expected: []validatedActiveElementSegment{
 				{opcode: OpcodeGlobalGet, arg: 0, init: []*Index{uint32Ptr(0)}},
 			},
 		},
@@ -285,7 +285,7 @@ func TestModule_validateTable(t *testing.T) {
 					},
 				},
 			},
-			expected: []*validatedActiveElementSegment{
+			expected: []validatedActiveElementSegment{
 				{opcode: OpcodeGlobalGet, arg: 1, init: []*Index{uint32Ptr(0), uint32Ptr(2)}},
 			},
 		},
@@ -313,7 +313,7 @@ func TestModule_validateTable(t *testing.T) {
 					},
 				},
 			},
-			expected: []*validatedActiveElementSegment{
+			expected: []validatedActiveElementSegment{
 				{opcode: OpcodeI32Const, arg: 1, init: []*Index{uint32Ptr(0), uint32Ptr(2)}},
 				{opcode: OpcodeGlobalGet, arg: 1, init: []*Index{uint32Ptr(1), uint32Ptr(2)}},
 			},
@@ -686,14 +686,14 @@ func TestModule_buildTables(t *testing.T) {
 		{
 			name: "empty",
 			module: &Module{
-				validatedActiveElementSegments: []*validatedActiveElementSegment{},
+				validatedActiveElementSegments: []validatedActiveElementSegment{},
 			},
 		},
 		{
 			name: "min zero",
 			module: &Module{
 				TableSection:                   []Table{{Type: RefTypeFuncref}},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{},
+				validatedActiveElementSegments: []validatedActiveElementSegment{},
 			},
 			expectedTables: []*TableInstance{{References: make([]Reference, 0), Min: 0, Type: RefTypeFuncref}},
 		},
@@ -701,7 +701,7 @@ func TestModule_buildTables(t *testing.T) {
 			name: "min/max",
 			module: &Module{
 				TableSection:                   []Table{{Min: 1, Max: &three}},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{},
+				validatedActiveElementSegments: []validatedActiveElementSegment{},
 			},
 			expectedTables: []*TableInstance{{References: make([]Reference, 1), Min: 1, Max: &three}},
 		},
@@ -712,7 +712,7 @@ func TestModule_buildTables(t *testing.T) {
 				TableSection:                   []Table{{Min: 1}},
 				FunctionSection:                []Index{0},
 				CodeSection:                    []*Code{codeEnd},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{},
+				validatedActiveElementSegments: []validatedActiveElementSegment{},
 			},
 			expectedTables: []*TableInstance{{References: make([]Reference, 1), Min: 1}},
 		},
@@ -720,7 +720,7 @@ func TestModule_buildTables(t *testing.T) {
 			name: "null extern refs",
 			module: &Module{
 				TableSection: []Table{{Min: 10, Type: RefTypeExternref}},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeI32Const, arg: 5, init: []*Index{nil, nil, nil}}, // three null refs.
 				},
 			},
@@ -734,7 +734,7 @@ func TestModule_buildTables(t *testing.T) {
 				TableSection:    []Table{{Min: 1}},
 				FunctionSection: []Index{0},
 				CodeSection:     []*Code{codeEnd},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeI32Const, arg: 0, init: []*Index{uint32Ptr(0)}},
 				},
 			},
@@ -747,7 +747,7 @@ func TestModule_buildTables(t *testing.T) {
 				TypeSection:     []*FunctionType{{}},
 				FunctionSection: []Index{0},
 				CodeSection:     []*Code{codeEnd},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeI32Const, arg: 0, init: []*Index{uint32Ptr(0)}},
 				},
 			},
@@ -762,7 +762,7 @@ func TestModule_buildTables(t *testing.T) {
 				ImportSection:   []Import{{Type: ExternTypeTable, DescTable: Table{Min: 1}}},
 				FunctionSection: []Index{0},
 				CodeSection:     []*Code{codeEnd},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeI32Const, arg: 0, init: []*Index{uint32Ptr(0)}},
 				},
 			},
@@ -777,7 +777,7 @@ func TestModule_buildTables(t *testing.T) {
 				TableSection:    []Table{{Min: 3}},
 				FunctionSection: []Index{0, 0, 0, 0},
 				CodeSection:     []*Code{codeEnd, codeEnd, codeEnd, codeEnd},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeI32Const, arg: 1, init: []*Index{uint32Ptr(0), uint32Ptr(2)}},
 				},
 			},
@@ -794,7 +794,7 @@ func TestModule_buildTables(t *testing.T) {
 				TableSection:                   []Table{{Min: 1}},
 				FunctionSection:                []Index{0},
 				CodeSection:                    []*Code{codeEnd},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{},
+				validatedActiveElementSegments: []validatedActiveElementSegment{},
 			},
 			importedGlobals: []*GlobalInstance{{Type: GlobalType{ValType: ValueTypeI32}, Val: 1}},
 			expectedTables:  []*TableInstance{{References: make([]Reference, 1), Min: 1}},
@@ -809,7 +809,7 @@ func TestModule_buildTables(t *testing.T) {
 				TableSection:    []Table{{Min: 2}},
 				FunctionSection: []Index{0},
 				CodeSection:     []*Code{codeEnd},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeGlobalGet, arg: 0, init: []*Index{uint32Ptr(0)}},
 				},
 			},
@@ -827,7 +827,7 @@ func TestModule_buildTables(t *testing.T) {
 				},
 				FunctionSection: []Index{0},
 				CodeSection:     []*Code{codeEnd},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeGlobalGet, arg: 0, init: []*Index{uint32Ptr(0)}},
 				},
 			},
@@ -846,7 +846,7 @@ func TestModule_buildTables(t *testing.T) {
 				},
 				FunctionSection: []Index{0},
 				CodeSection:     []*Code{codeEnd},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeGlobalGet, arg: 0, init: []*Index{uint32Ptr(0)}},
 				},
 			},
@@ -878,7 +878,7 @@ func TestModule_buildTables(t *testing.T) {
 						TableIndex: 0,
 					},
 				},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{tableIndex: 1, opcode: OpcodeGlobalGet, arg: 0, init: []*Index{nil, uint32Ptr(2)}},
 					{tableIndex: 0, opcode: OpcodeGlobalGet, arg: 1, init: []*Index{uint32Ptr(0), uint32Ptr(2)}},
 				},
@@ -907,7 +907,7 @@ func TestModule_buildTables(t *testing.T) {
 				TableSection:    []Table{{Min: 3}},
 				FunctionSection: []Index{0, 0, 0, 0},
 				CodeSection:     []*Code{codeEnd, codeEnd, codeEnd, codeEnd},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeI32Const, arg: 1, init: []*Index{uint32Ptr(0), uint32Ptr(2)}},
 					{opcode: OpcodeGlobalGet, arg: 1, init: []*Index{uint32Ptr(1), uint32Ptr(2)}},
 				},
@@ -959,7 +959,7 @@ func TestModule_buildTable_Errors(t *testing.T) {
 						Init:       []*Index{uint32Ptr(0)},
 					},
 				},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeI32Const, arg: 2, init: []*Index{uint32Ptr(0)}},
 				},
 			},
@@ -982,7 +982,7 @@ func TestModule_buildTable_Errors(t *testing.T) {
 						Init:       []*Index{uint32Ptr(0)},
 					},
 				},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeGlobalGet, arg: 0, init: []*Index{uint32Ptr(0)}},
 				},
 			},
@@ -1006,7 +1006,7 @@ func TestModule_buildTable_Errors(t *testing.T) {
 						Init:       []*Index{uint32Ptr(0)},
 					},
 				},
-				validatedActiveElementSegments: []*validatedActiveElementSegment{
+				validatedActiveElementSegments: []validatedActiveElementSegment{
 					{opcode: OpcodeGlobalGet, arg: 0, init: []*Index{uint32Ptr(0)}},
 				},
 			},
diff --git a/internal/wazeroir/compiler_test.go b/internal/wazeroir/compiler_test.go
index 2b49a272..7b4cc4f6 100644
--- a/internal/wazeroir/compiler_test.go
+++ b/internal/wazeroir/compiler_test.go
@@ -2935,7 +2935,7 @@ func TestCompile_select_vectors(t *testing.T) {
 					wasm.OpcodeDrop,
 					wasm.OpcodeEnd,
 				}}},
-				FunctionDefinitionSection: []*wasm.FunctionDefinition{{}},
+				FunctionDefinitionSection: []wasm.FunctionDefinition{{}},
 			},
 			expected: []Operation{
 				OperationV128Const{Lo: 0x1, Hi: 0x2},
@@ -2961,7 +2961,7 @@ func TestCompile_select_vectors(t *testing.T) {
 					wasm.OpcodeDrop,
 					wasm.OpcodeEnd,
 				}}},
-				FunctionDefinitionSection: []*wasm.FunctionDefinition{{}},
+				FunctionDefinitionSection: []wasm.FunctionDefinition{{}},
 			},
 			expected: []Operation{
 				OperationV128Const{Lo: 0x1, Hi: 0x2},