Repository: tetratelabs/wazero
Pull request #902 (2022-12-08 03:34:27)

Makes log listener default to signed interpretation
This changes the log listener to assume a value is signed instead of unsigned, as it leads to logs looking more correct than the other way around. Notably, values that are often negative, such as seek offset, look better without a lot of downside.

discussed with @anuraaga 


Patch:
diff --git a/.github/workflows/commit.yaml b/.github/workflows/commit.yaml
index 93e735c9..f7011e5a 100644
--- a/.github/workflows/commit.yaml
+++ b/.github/workflows/commit.yaml
@@ -20,6 +20,11 @@ defaults:
   run:  # use bash for all operating systems unless overridden
     shell: bash
 
+concurrency:
+  # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-using-concurrency-to-cancel-any-in-progress-job-or-run
+  group: ${{ github.head_ref }}
+  cancel-in-progress: true
+
 jobs:
   check:
     name: Pre-commit check, Go-${{ matrix.go-version }}
diff --git a/.github/workflows/examples.yaml b/.github/workflows/examples.yaml
index f0bbb416..9ef240d9 100644
--- a/.github/workflows/examples.yaml
+++ b/.github/workflows/examples.yaml
@@ -20,6 +20,11 @@ env:
   TINYGO_VERSION: "0.26.0"
   ZIG_VERSION: "0.11.0-dev.618+096d3efae"
 
+concurrency:
+  # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-using-concurrency-to-cancel-any-in-progress-job-or-run
+  group: ${{ github.head_ref }}
+  cancel-in-progress: true
+
 jobs:
   # Not all toolchains are idempotent when generating wasm, so we don't check
   # in %.wasm as a part of this job.
diff --git a/experimental/logging/log_listener.go b/experimental/logging/log_listener.go
index 5c523b53..9b707b55 100644
--- a/experimental/logging/log_listener.go
+++ b/experimental/logging/log_listener.go
@@ -183,14 +183,18 @@ func (l *loggingListener) writeParam(message *strings.Builder, i int, vals []uin
 	return l.writeVal(message, l.fnd.ParamTypes()[i], i, vals)
 }
 
+// writeVal formats integers as signed even though the call site determines
+// if it is signed or not. This presents a better experience for values that
+// are often signed, such as seek offset. This concedes the rare intentional
+// unsigned value at the end of its range will show up as negative.
 func (l *loggingListener) writeVal(message *strings.Builder, t api.ValueType, i int, vals []uint64) int {
 	v := vals[i]
 	i++
 	switch t {
 	case api.ValueTypeI32:
-		message.WriteString(strconv.FormatUint(uint64(uint32(v)), 10))
+		message.WriteString(strconv.FormatInt(int64(int32(v)), 10))
 	case api.ValueTypeI64:
-		message.WriteString(strconv.FormatUint(v, 10))
+		message.WriteString(strconv.FormatInt(int64(v), 10))
 	case api.ValueTypeF32:
 		message.WriteString(strconv.FormatFloat(float64(api.DecodeF32(v)), 'g', -1, 32))
 	case api.ValueTypeF64:
diff --git a/imports/wasi_snapshot_preview1/fs.go b/imports/wasi_snapshot_preview1/fs.go
index 722c9888..16d07669 100644
--- a/imports/wasi_snapshot_preview1/fs.go
+++ b/imports/wasi_snapshot_preview1/fs.go
@@ -410,7 +410,7 @@ var fdFilestatSetTimes = stubFunction(
 var fdPread = newHostFunc(
 	fdPreadName, fdPreadFn,
 	[]api.ValueType{i32, i32, i32, i64, i32},
-	"fd", "iovs", "iovs_len", "offset", "result.size",
+	"fd", "iovs", "iovs_len", "offset", "result.nread",
 )
 
 func fdPreadFn(ctx context.Context, mod api.Module, params []uint64) Errno {
@@ -550,13 +550,13 @@ var fdPwrite = stubFunction(
 //   - Both offset and length are encoded as uint32le
 //   - iovsCount: count of memory offset, size pairs to read sequentially
 //     starting at iovs
-//   - resultSize: offset in api.Memory to write the number of bytes read
+//   - resultNread: offset in api.Memory to write the number of bytes read
 //
 // Result (Errno)
 //
 // The return value is ErrnoSuccess except the following error conditions:
 //   - ErrnoBadf: `fd` is invalid
-//   - ErrnoFault: `iovs` or `resultSize` point to an offset out of memory
+//   - ErrnoFault: `iovs` or `resultNread` point to an offset out of memory
 //   - ErrnoIo: a file system error
 //
 // For example, this function needs to first read `iovs` to determine where
@@ -574,7 +574,7 @@ var fdPwrite = stubFunction(
 //	 offset --+   length --+   offset --+  length --+
 //
 // If the contents of the `fd` parameter was "wazero" (6 bytes) and parameter
-// resultSize=26, this function writes the below to api.Memory:
+// resultNread=26, this function writes the below to api.Memory:
 //
 //	                    iovs[0].length        iovs[1].length
 //	                   +--------------+       +----+       uint32le
@@ -582,7 +582,7 @@ var fdPwrite = stubFunction(
 //	[]byte{ 0..16, ?, 'w', 'a', 'z', 'e', ?, 'r', 'o', ?, 6, 0, 0, 0 }
 //	  iovs[0].offset --^                      ^           ^
 //	                         iovs[1].offset --+           |
-//	                                         resultSize --+
+//	                                        resultNread --+
 //
 // Note: This is similar to `readv` in POSIX. https://linux.die.net/man/3/readv
 //
@@ -591,7 +591,7 @@ var fdPwrite = stubFunction(
 var fdRead = newHostFunc(
 	fdReadName, fdReadFn,
 	[]api.ValueType{i32, i32, i32, i32},
-	"fd", "iovs", "iovs_len", "result.size",
+	"fd", "iovs", "iovs_len", "result.nread",
 )
 
 func fdReadFn(ctx context.Context, mod api.Module, params []uint64) Errno {
@@ -606,12 +606,12 @@ func fdReadOrPread(ctx context.Context, mod api.Module, params []uint64, isPread
 	iovsCount := uint32(params[2])
 
 	var offset int64
-	var resultSize uint32
+	var resultNread uint32
 	if isPread {
 		offset = int64(params[3])
-		resultSize = uint32(params[4])
+		resultNread = uint32(params[4])
 	} else {
-		resultSize = uint32(params[3])
+		resultNread = uint32(params[3])
 	}
 
 	r := internalsys.FdReader(ctx, sysCtx, fd)
@@ -655,7 +655,7 @@ func fdReadOrPread(ctx context.Context, mod api.Module, params []uint64, isPread
 			break
 		}
 	}
-	if !mem.WriteUint32Le(ctx, resultSize, nread) {
+	if !mem.WriteUint32Le(ctx, resultNread, nread) {
 		return ErrnoFault
 	} else {
 		return ErrnoSuccess
@@ -1042,13 +1042,14 @@ var fdTell = stubFunction(fdTellName, []wasm.ValueType{i32, i32}, "fd", "result.
 //   - Both offset and length are encoded as uint32le.
 //   - iovsCount: count of memory offset, size pairs to read sequentially
 //     starting at iovs
-//   - resultSize: offset in api.Memory to write the number of bytes written
+//   - resultNwritten: offset in api.Memory to write the number of bytes
+//     written
 //
 // Result (Errno)
 //
 // The return value is ErrnoSuccess except the following error conditions:
 //   - ErrnoBadf: `fd` is invalid
-//   - ErrnoFault: `iovs` or `resultSize` point to an offset out of memory
+//   - ErrnoFault: `iovs` or `resultNwritten` point to an offset out of memory
 //   - ErrnoIo: a file system error
 //
 // For example, this function needs to first read `iovs` to determine what to
@@ -1074,14 +1075,14 @@ var fdTell = stubFunction(fdTellName, []wasm.ValueType{i32, i32}, "fd", "result.
 //	  iovs[0].offset --^                      ^
 //	                         iovs[1].offset --+
 //
-// Since "wazero" was written, if parameter resultSize=26, this function writes
-// the below to api.Memory:
+// Since "wazero" was written, if parameter resultNwritten=26, this function
+// writes the below to api.Memory:
 //
 //	                   uint32le
 //	                  +--------+
 //	                  |        |
 //	[]byte{ 0..24, ?, 6, 0, 0, 0', ? }
-//	     resultSize --^
+//	 resultNwritten --^
 //
 // Note: This is similar to `writev` in POSIX. https://linux.die.net/man/3/writev
 //
@@ -1091,14 +1092,14 @@ var fdTell = stubFunction(fdTellName, []wasm.ValueType{i32, i32}, "fd", "result.
 var fdWrite = newHostFunc(
 	fdWriteName, fdWriteFn,
 	[]api.ValueType{i32, i32, i32, i32},
-	"fd", "iovs", "iovs_len", "result.size",
+	"fd", "iovs", "iovs_len", "result.nwritten",
 )
 
 func fdWriteFn(ctx context.Context, mod api.Module, params []uint64) Errno {
 	fd := uint32(params[0])
 	iovs := uint32(params[1])
 	iovsCount := uint32(params[2])
-	resultSize := uint32(params[3])
+	resultNwritten := uint32(params[3])
 
 	sysCtx := mod.(*wasm.CallContext).Sys
 	writer := internalsys.FdWriter(ctx, sysCtx, fd)
@@ -1136,7 +1137,7 @@ func fdWriteFn(ctx context.Context, mod api.Module, params []uint64) Errno {
 		}
 		nwritten += uint32(n)
 	}
-	if !mod.Memory().WriteUint32Le(ctx, resultSize, nwritten) {
+	if !mod.Memory().WriteUint32Le(ctx, resultNwritten, nwritten) {
 		return ErrnoFault
 	}
 	return ErrnoSuccess
diff --git a/internal/wasm/namespace.go b/internal/wasm/namespace.go
index 78d44992..029ddaa5 100644
--- a/internal/wasm/namespace.go
+++ b/internal/wasm/namespace.go
@@ -8,13 +8,19 @@ import (
 	"github.com/tetratelabs/wazero/api"
 )
 
+// nameListNode is a node in a doubly linked list of names.
+type nameListNode struct {
+	name       string
+	next, prev *nameListNode
+}
+
 // Namespace is a collection of instantiated modules which cannot conflict on name.
 type Namespace struct {
 	// moduleNamesList ensures modules are closed in reverse initialization order.
-	moduleNamesList []string // guarded by mux
+	moduleNamesList *nameListNode // guarded by mux
 
 	// moduleNamesSet ensures no race conditions instantiating two modules of the same name
-	moduleNamesSet map[string]struct{} // guarded by mux
+	moduleNamesSet map[string]*nameListNode // guarded by mux
 
 	// modules holds the instantiated Wasm modules by module name from Instantiate.
 	modules map[string]*ModuleInstance // guarded by mux
@@ -27,7 +33,7 @@ type Namespace struct {
 func newNamespace() *Namespace {
 	return &Namespace{
 		moduleNamesList: nil,
-		moduleNamesSet:  map[string]struct{}{},
+		moduleNamesSet:  map[string]*nameListNode{},
 		modules:         map[string]*ModuleInstance{},
 	}
 }
@@ -43,15 +49,23 @@ func (ns *Namespace) addModule(m *ModuleInstance) {
 func (ns *Namespace) deleteModule(moduleName string) {
 	ns.mux.Lock()
 	defer ns.mux.Unlock()
-	delete(ns.modules, moduleName)
-	delete(ns.moduleNamesSet, moduleName)
+	node, ok := ns.moduleNamesSet[moduleName]
+	if !ok {
+		return
+	}
+
 	// remove this module name
-	for i, n := range ns.moduleNamesList {
-		if n == moduleName {
-			ns.moduleNamesList = append(ns.moduleNamesList[:i], ns.moduleNamesList[i+1:]...)
-			break
-		}
+	if node.prev == nil {
+		ns.moduleNamesList = node.next
+	} else {
+		node.prev.next = node.next
 	}
+	if node.next != nil {
+		node.next.prev = node.prev
+	}
+
+	delete(ns.modules, moduleName)
+	delete(ns.moduleNamesSet, moduleName)
 }
 
 // module returns the module of the given name or nil if not in this namespace
@@ -86,8 +100,17 @@ func (ns *Namespace) requireModuleName(moduleName string) error {
 	if _, ok := ns.moduleNamesSet[moduleName]; ok {
 		return fmt.Errorf("module[%s] has already been instantiated", moduleName)
 	}
-	ns.moduleNamesSet[moduleName] = struct{}{}
-	ns.moduleNamesList = append(ns.moduleNamesList, moduleName)
+
+	// add the newest node to the moduleNamesList as the head.
+	node := &nameListNode{
+		name: moduleName,
+		next: ns.moduleNamesList,
+	}
+	if node.next != nil {
+		node.next.prev = node
+	}
+	ns.moduleNamesList = node
+	ns.moduleNamesSet[moduleName] = node
 	return nil
 }
 
@@ -103,16 +126,16 @@ func (ns *Namespace) CloseWithExitCode(ctx context.Context, exitCode uint32) (er
 	ns.mux.Lock()
 	defer ns.mux.Unlock()
 	// Close modules in reverse initialization order.
-	for i := len(ns.moduleNamesList) - 1; i >= 0; i-- {
+	for node := ns.moduleNamesList; node != nil; node = node.next {
 		// If closing this module errs, proceed anyway to close the others.
-		if m, ok := ns.modules[ns.moduleNamesList[i]]; ok {
+		if m, ok := ns.modules[node.name]; ok {
 			if _, e := m.CallCtx.close(ctx, exitCode); e != nil && err == nil {
 				err = e // first error
 			}
 		}
 	}
 	ns.moduleNamesList = nil
-	ns.moduleNamesSet = map[string]struct{}{}
+	ns.moduleNamesSet = map[string]*nameListNode{}
 	ns.modules = map[string]*ModuleInstance{}
 	return
 }


Test patch:
diff --git a/.github/workflows/spectest.yaml b/.github/workflows/spectest.yaml
index 9d12bc24..0d9fb55a 100644
--- a/.github/workflows/spectest.yaml
+++ b/.github/workflows/spectest.yaml
@@ -17,6 +17,11 @@ defaults:
   run:  # use bash for all operating systems unless overridden
     shell: bash
 
+concurrency:
+  # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-using-concurrency-to-cancel-any-in-progress-job-or-run
+  group: ${{ github.head_ref }}
+  cancel-in-progress: true
+
 jobs:
   test_amd64:
     name: ${{ matrix.spec-version }} - linux/amd64, Go-${{ matrix.go-version }}
diff --git a/experimental/logging/log_listener_test.go b/experimental/logging/log_listener_test.go
index 9f4fffbb..751c2af8 100644
--- a/experimental/logging/log_listener_test.go
+++ b/experimental/logging/log_listener_test.go
@@ -106,7 +106,7 @@ func Test_loggingListener(t *testing.T) {
 			name:     "i32",
 			functype: &wasm.FunctionType{Params: []api.ValueType{api.ValueTypeI32}},
 			params:   []uint64{math.MaxUint32},
-			expected: `--> test.fn(4294967295)
+			expected: `--> test.fn(-1)
 <--
 `,
 		},
@@ -115,7 +115,7 @@ func Test_loggingListener(t *testing.T) {
 			functype:   &wasm.FunctionType{Params: []api.ValueType{api.ValueTypeI32}},
 			params:     []uint64{math.MaxUint32},
 			paramNames: []string{"x"},
-			expected: `--> test.fn(x=4294967295)
+			expected: `--> test.fn(x=-1)
 <--
 `,
 		},
@@ -123,7 +123,7 @@ func Test_loggingListener(t *testing.T) {
 			name:     "i64",
 			functype: &wasm.FunctionType{Params: []api.ValueType{api.ValueTypeI64}},
 			params:   []uint64{math.MaxUint64},
-			expected: `--> test.fn(18446744073709551615)
+			expected: `--> test.fn(-1)
 <--
 `,
 		},
@@ -132,7 +132,7 @@ func Test_loggingListener(t *testing.T) {
 			functype:   &wasm.FunctionType{Params: []api.ValueType{api.ValueTypeI64}},
 			params:     []uint64{math.MaxUint64},
 			paramNames: []string{"x"},
-			expected: `--> test.fn(x=18446744073709551615)
+			expected: `--> test.fn(x=-1)
 <--
 `,
 		},
@@ -226,7 +226,7 @@ func Test_loggingListener(t *testing.T) {
 			functype: &wasm.FunctionType{Results: []api.ValueType{api.ValueTypeI32}},
 			results:  []uint64{math.MaxUint32},
 			expected: `--> test.fn()
-<-- 4294967295
+<-- -1
 `,
 		},
 		{
@@ -237,7 +237,7 @@ func Test_loggingListener(t *testing.T) {
 			},
 			params:  []uint64{math.MaxUint32},
 			results: []uint64{api.EncodeF32(math.MaxFloat32)},
-			expected: `--> test.fn(4294967295)
+			expected: `--> test.fn(-1)
 <-- 3.4028235e+38
 `,
 		},
@@ -249,7 +249,7 @@ func Test_loggingListener(t *testing.T) {
 			},
 			params:  []uint64{math.MaxUint32, math.MaxUint64},
 			results: []uint64{api.EncodeF32(math.MaxFloat32), api.EncodeF64(math.MaxFloat64)},
-			expected: `--> test.fn(4294967295,18446744073709551615)
+			expected: `--> test.fn(-1,-1)
 <-- (3.4028235e+38,1.7976931348623157e+308)
 `,
 		},
@@ -262,7 +262,7 @@ func Test_loggingListener(t *testing.T) {
 			params:     []uint64{math.MaxUint32, math.MaxUint64},
 			paramNames: []string{"x", "y"},
 			results:    []uint64{api.EncodeF32(math.MaxFloat32), api.EncodeF64(math.MaxFloat64)},
-			expected: `--> test.fn(x=4294967295,y=18446744073709551615)
+			expected: `--> test.fn(x=-1,y=-1)
 <-- (3.4028235e+38,1.7976931348623157e+308)
 `,
 		},
diff --git a/imports/wasi_snapshot_preview1/fs_test.go b/imports/wasi_snapshot_preview1/fs_test.go
index d009dc74..897260e2 100644
--- a/imports/wasi_snapshot_preview1/fs_test.go
+++ b/imports/wasi_snapshot_preview1/fs_test.go
@@ -223,8 +223,8 @@ func Test_fdFdstatGet(t *testing.T) {
 			fd:            math.MaxUint32,
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
---> proxy.fd_fdstat_get(fd=4294967295,result.stat=0)
-	==> wasi_snapshot_preview1.fd_fdstat_get(fd=4294967295,result.stat=0)
+--> proxy.fd_fdstat_get(fd=-1,result.stat=0)
+	==> wasi_snapshot_preview1.fd_fdstat_get(fd=-1,result.stat=0)
 	<== EBADF
 <-- 8
 `,
@@ -432,8 +432,8 @@ func Test_fdFilestatGet(t *testing.T) {
 			fd:            math.MaxUint32,
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
---> proxy.fd_filestat_get(fd=4294967295,result.buf=0)
-	==> wasi_snapshot_preview1.fd_filestat_get(fd=4294967295,result.buf=0)
+--> proxy.fd_filestat_get(fd=-1,result.buf=0)
+	==> wasi_snapshot_preview1.fd_filestat_get(fd=-1,result.buf=0)
 	<== EBADF
 <-- 8
 `,
@@ -506,8 +506,8 @@ func Test_fdPread(t *testing.T) {
 		'?',
 	}
 
-	iovsCount := uint32(2)   // The count of iovs
-	resultSize := uint32(26) // arbitrary offset
+	iovsCount := uint32(2)    // The count of iovs
+	resultNread := uint32(26) // arbitrary offset
 
 	tests := []struct {
 		name           string
@@ -523,13 +523,13 @@ func Test_fdPread(t *testing.T) {
 				'w', 'a', 'z', 'e', // iovs[0].length bytes
 				'?',      // iovs[1].offset is after this
 				'r', 'o', // iovs[1].length bytes
-				'?',        // resultSize is after this
+				'?',        // resultNread is after this
 				6, 0, 0, 0, // sum(iovs[...].length) == length of "wazero"
 				'?',
 			),
 			expectedLog: `
---> proxy.fd_pread(fd=4,iovs=1,iovs_len=2,offset=0,result.size=26)
-	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=1,iovs_len=2,offset=0,result.size=26)
+--> proxy.fd_pread(fd=4,iovs=1,iovs_len=2,offset=0,result.nread=26)
+	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=1,iovs_len=2,offset=0,result.nread=26)
 	<== ESUCCESS
 <-- 0
 `,
@@ -540,13 +540,13 @@ func Test_fdPread(t *testing.T) {
 			expectedMemory: append(
 				initialMemory,
 				'z', 'e', 'r', 'o', // iovs[0].length bytes
-				'?', '?', '?', '?', // resultSize is after this
+				'?', '?', '?', '?', // resultNread is after this
 				4, 0, 0, 0, // sum(iovs[...].length) == length of "zero"
 				'?',
 			),
 			expectedLog: `
---> proxy.fd_pread(fd=4,iovs=1,iovs_len=2,offset=2,result.size=26)
-	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=1,iovs_len=2,offset=2,result.size=26)
+--> proxy.fd_pread(fd=4,iovs=1,iovs_len=2,offset=2,result.nread=26)
+	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=1,iovs_len=2,offset=2,result.nread=26)
 	<== ESUCCESS
 <-- 0
 `,
@@ -563,7 +563,7 @@ func Test_fdPread(t *testing.T) {
 			ok := mod.Memory().Write(testCtx, 0, initialMemory)
 			require.True(t, ok)
 
-			requireErrno(t, ErrnoSuccess, mod, fdPreadName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(tc.offset), uint64(resultSize))
+			requireErrno(t, ErrnoSuccess, mod, fdPreadName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(tc.offset), uint64(resultNread))
 			require.Equal(t, tc.expectedLog, "\n"+log.String())
 
 			actual, ok := mod.Memory().Read(testCtx, 0, uint32(len(tc.expectedMemory)))
@@ -579,20 +579,20 @@ func Test_fdPread_Errors(t *testing.T) {
 	defer r.Close(testCtx)
 
 	tests := []struct {
-		name                            string
-		fd, iovs, iovsCount, resultSize uint32
-		offset                          int64
-		memory                          []byte
-		expectedErrno                   Errno
-		expectedLog                     string
+		name                             string
+		fd, iovs, iovsCount, resultNread uint32
+		offset                           int64
+		memory                           []byte
+		expectedErrno                    Errno
+		expectedLog                      string
 	}{
 		{
 			name:          "invalid fd",
 			fd:            42, // arbitrary invalid fd
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
---> proxy.fd_pread(fd=42,iovs=65536,iovs_len=65536,offset=0,result.size=65536)
-	==> wasi_snapshot_preview1.fd_pread(fd=42,iovs=65536,iovs_len=65536,offset=0,result.size=65536)
+--> proxy.fd_pread(fd=42,iovs=65536,iovs_len=65536,offset=0,result.nread=65536)
+	==> wasi_snapshot_preview1.fd_pread(fd=42,iovs=65536,iovs_len=65536,offset=0,result.nread=65536)
 	<== EBADF
 <-- 8
 `,
@@ -603,8 +603,8 @@ func Test_fdPread_Errors(t *testing.T) {
 			offset:        int64(len(contents) + 1),
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_pread(fd=4,iovs=65536,iovs_len=65536,offset=7,result.size=65536)
-	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65536,iovs_len=65536,offset=7,result.size=65536)
+--> proxy.fd_pread(fd=4,iovs=65536,iovs_len=65536,offset=7,result.nread=65536)
+	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65536,iovs_len=65536,offset=7,result.nread=65536)
 	<== EFAULT
 <-- 21
 `,
@@ -616,8 +616,8 @@ func Test_fdPread_Errors(t *testing.T) {
 			memory:        []byte{'?'},
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_pread(fd=4,iovs=65536,iovs_len=65535,offset=0,result.size=65535)
-	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65536,iovs_len=65535,offset=0,result.size=65535)
+--> proxy.fd_pread(fd=4,iovs=65536,iovs_len=65535,offset=0,result.nread=65535)
+	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65536,iovs_len=65535,offset=0,result.nread=65535)
 	<== EFAULT
 <-- 21
 `,
@@ -632,8 +632,8 @@ func Test_fdPread_Errors(t *testing.T) {
 			},
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_pread(fd=4,iovs=65532,iovs_len=65532,offset=0,result.size=65531)
-	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65532,iovs_len=65532,offset=0,result.size=65531)
+--> proxy.fd_pread(fd=4,iovs=65532,iovs_len=65532,offset=0,result.nread=65531)
+	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65532,iovs_len=65532,offset=0,result.nread=65531)
 	<== EFAULT
 <-- 21
 `,
@@ -649,8 +649,8 @@ func Test_fdPread_Errors(t *testing.T) {
 			},
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_pread(fd=4,iovs=65528,iovs_len=65528,offset=0,result.size=65527)
-	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65528,iovs_len=65528,offset=0,result.size=65527)
+--> proxy.fd_pread(fd=4,iovs=65528,iovs_len=65528,offset=0,result.nread=65527)
+	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65528,iovs_len=65528,offset=0,result.nread=65527)
 	<== EFAULT
 <-- 21
 `,
@@ -667,17 +667,17 @@ func Test_fdPread_Errors(t *testing.T) {
 			},
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_pread(fd=4,iovs=65527,iovs_len=65527,offset=0,result.size=65526)
-	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65527,iovs_len=65527,offset=0,result.size=65526)
+--> proxy.fd_pread(fd=4,iovs=65527,iovs_len=65527,offset=0,result.nread=65526)
+	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65527,iovs_len=65527,offset=0,result.nread=65526)
 	<== EFAULT
 <-- 21
 `,
 		},
 		{
-			name: "resultSize offset is outside memory",
+			name: "resultNread offset is outside memory",
 			fd:   fd,
 			iovs: 1, iovsCount: 1,
-			resultSize: 10, // 1 past memory
+			resultNread: 10, // 1 past memory
 			memory: []byte{
 				'?',        // `iovs` is after this
 				9, 0, 0, 0, // = iovs[0].offset
@@ -686,8 +686,8 @@ func Test_fdPread_Errors(t *testing.T) {
 			},
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_pread(fd=4,iovs=65527,iovs_len=65527,offset=0,result.size=65536)
-	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65527,iovs_len=65527,offset=0,result.size=65536)
+--> proxy.fd_pread(fd=4,iovs=65527,iovs_len=65527,offset=0,result.nread=65536)
+	==> wasi_snapshot_preview1.fd_pread(fd=4,iovs=65527,iovs_len=65527,offset=0,result.nread=65536)
 	<== EFAULT
 <-- 21
 `,
@@ -704,7 +704,7 @@ func Test_fdPread_Errors(t *testing.T) {
 			memoryWriteOK := mod.Memory().Write(testCtx, offset, tc.memory)
 			require.True(t, memoryWriteOK)
 
-			requireErrno(t, tc.expectedErrno, mod, fdPreadName, uint64(tc.fd), uint64(tc.iovs+offset), uint64(tc.iovsCount+offset), uint64(tc.offset), uint64(tc.resultSize+offset))
+			requireErrno(t, tc.expectedErrno, mod, fdPreadName, uint64(tc.fd), uint64(tc.iovs+offset), uint64(tc.iovsCount+offset), uint64(tc.offset), uint64(tc.resultNread+offset))
 			require.Equal(t, tc.expectedLog, "\n"+log.String())
 		})
 	}
@@ -928,14 +928,14 @@ func Test_fdRead(t *testing.T) {
 		2, 0, 0, 0, // = iovs[1].length
 		'?',
 	}
-	iovsCount := uint32(2)   // The count of iovs
-	resultSize := uint32(26) // arbitrary offset
+	iovsCount := uint32(2)    // The count of iovs
+	resultNread := uint32(26) // arbitrary offset
 	expectedMemory := append(
 		initialMemory,
 		'w', 'a', 'z', 'e', // iovs[0].length bytes
 		'?',      // iovs[1].offset is after this
 		'r', 'o', // iovs[1].length bytes
-		'?',        // resultSize is after this
+		'?',        // resultNread is after this
 		6, 0, 0, 0, // sum(iovs[...].length) == length of "wazero"
 		'?',
 	)
@@ -945,10 +945,10 @@ func Test_fdRead(t *testing.T) {
 	ok := mod.Memory().Write(testCtx, 0, initialMemory)
 	require.True(t, ok)
 
-	requireErrno(t, ErrnoSuccess, mod, fdReadName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(resultSize))
+	requireErrno(t, ErrnoSuccess, mod, fdReadName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(resultNread))
 	require.Equal(t, `
---> proxy.fd_read(fd=4,iovs=1,iovs_len=2,result.size=26)
-	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=1,iovs_len=2,result.size=26)
+--> proxy.fd_read(fd=4,iovs=1,iovs_len=2,result.nread=26)
+	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=1,iovs_len=2,result.nread=26)
 	<== ESUCCESS
 <-- 0
 `, "\n"+log.String())
@@ -963,19 +963,19 @@ func Test_fdRead_Errors(t *testing.T) {
 	defer r.Close(testCtx)
 
 	tests := []struct {
-		name                            string
-		fd, iovs, iovsCount, resultSize uint32
-		memory                          []byte
-		expectedErrno                   Errno
-		expectedLog                     string
+		name                             string
+		fd, iovs, iovsCount, resultNread uint32
+		memory                           []byte
+		expectedErrno                    Errno
+		expectedLog                      string
 	}{
 		{
 			name:          "invalid fd",
 			fd:            42, // arbitrary invalid fd
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
---> proxy.fd_read(fd=42,iovs=65536,iovs_len=65536,result.size=65536)
-	==> wasi_snapshot_preview1.fd_read(fd=42,iovs=65536,iovs_len=65536,result.size=65536)
+--> proxy.fd_read(fd=42,iovs=65536,iovs_len=65536,result.nread=65536)
+	==> wasi_snapshot_preview1.fd_read(fd=42,iovs=65536,iovs_len=65536,result.nread=65536)
 	<== EBADF
 <-- 8
 `,
@@ -987,8 +987,8 @@ func Test_fdRead_Errors(t *testing.T) {
 			memory:        []byte{'?'},
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_read(fd=4,iovs=65536,iovs_len=65535,result.size=65535)
-	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=65536,iovs_len=65535,result.size=65535)
+--> proxy.fd_read(fd=4,iovs=65536,iovs_len=65535,result.nread=65535)
+	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=65536,iovs_len=65535,result.nread=65535)
 	<== EFAULT
 <-- 21
 `,
@@ -1003,8 +1003,8 @@ func Test_fdRead_Errors(t *testing.T) {
 			},
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_read(fd=4,iovs=65532,iovs_len=65532,result.size=65531)
-	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=65532,iovs_len=65532,result.size=65531)
+--> proxy.fd_read(fd=4,iovs=65532,iovs_len=65532,result.nread=65531)
+	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=65532,iovs_len=65532,result.nread=65531)
 	<== EFAULT
 <-- 21
 `,
@@ -1020,8 +1020,8 @@ func Test_fdRead_Errors(t *testing.T) {
 			},
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_read(fd=4,iovs=65528,iovs_len=65528,result.size=65527)
-	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=65528,iovs_len=65528,result.size=65527)
+--> proxy.fd_read(fd=4,iovs=65528,iovs_len=65528,result.nread=65527)
+	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=65528,iovs_len=65528,result.nread=65527)
 	<== EFAULT
 <-- 21
 `,
@@ -1038,17 +1038,17 @@ func Test_fdRead_Errors(t *testing.T) {
 			},
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_read(fd=4,iovs=65527,iovs_len=65527,result.size=65526)
-	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=65527,iovs_len=65527,result.size=65526)
+--> proxy.fd_read(fd=4,iovs=65527,iovs_len=65527,result.nread=65526)
+	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=65527,iovs_len=65527,result.nread=65526)
 	<== EFAULT
 <-- 21
 `,
 		},
 		{
-			name: "resultSize offset is outside memory",
+			name: "resultNread offset is outside memory",
 			fd:   fd,
 			iovs: 1, iovsCount: 1,
-			resultSize: 10, // 1 past memory
+			resultNread: 10, // 1 past memory
 			memory: []byte{
 				'?',        // `iovs` is after this
 				9, 0, 0, 0, // = iovs[0].offset
@@ -1057,8 +1057,8 @@ func Test_fdRead_Errors(t *testing.T) {
 			},
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_read(fd=4,iovs=65527,iovs_len=65527,result.size=65536)
-	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=65527,iovs_len=65527,result.size=65536)
+--> proxy.fd_read(fd=4,iovs=65527,iovs_len=65527,result.nread=65536)
+	==> wasi_snapshot_preview1.fd_read(fd=4,iovs=65527,iovs_len=65527,result.nread=65536)
 	<== EFAULT
 <-- 21
 `,
@@ -1075,7 +1075,7 @@ func Test_fdRead_Errors(t *testing.T) {
 			memoryWriteOK := mod.Memory().Write(testCtx, offset, tc.memory)
 			require.True(t, memoryWriteOK)
 
-			requireErrno(t, tc.expectedErrno, mod, fdReadName, uint64(tc.fd), uint64(tc.iovs+offset), uint64(tc.iovsCount+offset), uint64(tc.resultSize+offset))
+			requireErrno(t, tc.expectedErrno, mod, fdReadName, uint64(tc.fd), uint64(tc.iovs+offset), uint64(tc.iovsCount+offset), uint64(tc.resultNread+offset))
 			require.Equal(t, tc.expectedLog, "\n"+log.String())
 		})
 	}
@@ -1621,8 +1621,8 @@ func Test_fdReaddir_Errors(t *testing.T) {
 			resultBufused: 2000,
 			expectedErrno: ErrnoInval,
 			expectedLog: `
---> proxy.fd_readdir(fd=4,buf=0,buf_len=1000,cookie=18446744073709551615,result.bufused=2000)
-	==> wasi_snapshot_preview1.fd_readdir(fd=4,buf=0,buf_len=1000,cookie=18446744073709551615,result.bufused=2000)
+--> proxy.fd_readdir(fd=4,buf=0,buf_len=1000,cookie=-1,result.bufused=2000)
+	==> wasi_snapshot_preview1.fd_readdir(fd=4,buf=0,buf_len=1000,cookie=-1,result.bufused=2000)
 	<== EINVAL
 <-- 28
 `,
@@ -1944,8 +1944,8 @@ func Test_fdSeek(t *testing.T) {
 				'?',
 			},
 			expectedLog: `
---> proxy.fd_seek(fd=4,offset=18446744073709551615,whence=2,result.newoffset=1)
-	==> wasi_snapshot_preview1.fd_seek(fd=4,offset=18446744073709551615,whence=2,result.newoffset=1)
+--> proxy.fd_seek(fd=4,offset=-1,whence=2,result.newoffset=1)
+	==> wasi_snapshot_preview1.fd_seek(fd=4,offset=-1,whence=2,result.newoffset=1)
 	<== ESUCCESS
 <-- 0
 `,
@@ -2087,8 +2087,8 @@ func Test_fdWrite(t *testing.T) {
 		'r', 'o', // iovs[1].length bytes
 		'?',
 	}
-	iovsCount := uint32(2)   // The count of iovs
-	resultSize := uint32(26) // arbitrary offset
+	iovsCount := uint32(2)       // The count of iovs
+	resultNwritten := uint32(26) // arbitrary offset
 	expectedMemory := append(
 		initialMemory,
 		6, 0, 0, 0, // sum(iovs[...].length) == length of "wazero"
@@ -2099,10 +2099,10 @@ func Test_fdWrite(t *testing.T) {
 	ok := mod.Memory().Write(testCtx, 0, initialMemory)
 	require.True(t, ok)
 
-	requireErrno(t, ErrnoSuccess, mod, fdWriteName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(resultSize))
+	requireErrno(t, ErrnoSuccess, mod, fdWriteName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(resultNwritten))
 	require.Equal(t, `
---> proxy.fd_write(fd=4,iovs=1,iovs_len=2,result.size=26)
-	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=1,iovs_len=2,result.size=26)
+--> proxy.fd_write(fd=4,iovs=1,iovs_len=2,result.nwritten=26)
+	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=1,iovs_len=2,result.nwritten=26)
 	<== ESUCCESS
 <-- 0
 `, "\n"+log.String())
@@ -2139,8 +2139,8 @@ func Test_fdWrite_discard(t *testing.T) {
 		'r', 'o', // iovs[1].length bytes
 		'?',
 	}
-	iovsCount := uint32(2)   // The count of iovs
-	resultSize := uint32(26) // arbitrary offset
+	iovsCount := uint32(2)       // The count of iovs
+	resultNwritten := uint32(26) // arbitrary offset
 	expectedMemory := append(
 		initialMemory,
 		6, 0, 0, 0, // sum(iovs[...].length) == length of "wazero"
@@ -2152,10 +2152,10 @@ func Test_fdWrite_discard(t *testing.T) {
 	require.True(t, ok)
 
 	fd := 1 // stdout
-	requireErrno(t, ErrnoSuccess, mod, fdWriteName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(resultSize))
+	requireErrno(t, ErrnoSuccess, mod, fdWriteName, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(resultNwritten))
 	require.Equal(t, `
---> proxy.fd_write(fd=1,iovs=1,iovs_len=2,result.size=26)
-	==> wasi_snapshot_preview1.fd_write(fd=1,iovs=1,iovs_len=2,result.size=26)
+--> proxy.fd_write(fd=1,iovs=1,iovs_len=2,result.nwritten=26)
+	==> wasi_snapshot_preview1.fd_write(fd=1,iovs=1,iovs_len=2,result.nwritten=26)
 	<== ESUCCESS
 <-- 0
 `, "\n"+log.String())
@@ -2180,19 +2180,19 @@ func Test_fdWrite_Errors(t *testing.T) {
 	}
 
 	tests := []struct {
-		name           string
-		fd, resultSize uint32
-		memory         []byte
-		expectedErrno  Errno
-		expectedLog    string
+		name               string
+		fd, resultNwritten uint32
+		memory             []byte
+		expectedErrno      Errno
+		expectedLog        string
 	}{
 		{
 			name:          "invalid fd",
 			fd:            42, // arbitrary invalid fd
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
---> proxy.fd_write(fd=42,iovs=0,iovs_len=1,result.size=0)
-	==> wasi_snapshot_preview1.fd_write(fd=42,iovs=0,iovs_len=1,result.size=0)
+--> proxy.fd_write(fd=42,iovs=0,iovs_len=1,result.nwritten=0)
+	==> wasi_snapshot_preview1.fd_write(fd=42,iovs=0,iovs_len=1,result.nwritten=0)
 	<== EBADF
 <-- 8
 `,
@@ -2203,8 +2203,8 @@ func Test_fdWrite_Errors(t *testing.T) {
 			memory:        []byte{},
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_write(fd=4,iovs=0,iovs_len=1,result.size=0)
-	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=0,iovs_len=1,result.size=0)
+--> proxy.fd_write(fd=4,iovs=0,iovs_len=1,result.nwritten=0)
+	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=0,iovs_len=1,result.nwritten=0)
 	<== EFAULT
 <-- 21
 `,
@@ -2215,8 +2215,8 @@ func Test_fdWrite_Errors(t *testing.T) {
 			memory:        memory[0:4], // iovs[0].offset was 4 bytes and iovs[0].length next, but not enough mod.Memory()!
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_write(fd=4,iovs=0,iovs_len=1,result.size=0)
-	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=0,iovs_len=1,result.size=0)
+--> proxy.fd_write(fd=4,iovs=0,iovs_len=1,result.nwritten=0)
+	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=0,iovs_len=1,result.nwritten=0)
 	<== EFAULT
 <-- 21
 `,
@@ -2227,8 +2227,8 @@ func Test_fdWrite_Errors(t *testing.T) {
 			memory:        memory[0:8], // iovs[0].offset (where to read "hi") is outside memory.
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_write(fd=4,iovs=0,iovs_len=1,result.size=0)
-	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=0,iovs_len=1,result.size=0)
+--> proxy.fd_write(fd=4,iovs=0,iovs_len=1,result.nwritten=0)
+	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=0,iovs_len=1,result.nwritten=0)
 	<== EFAULT
 <-- 21
 `,
@@ -2239,21 +2239,21 @@ func Test_fdWrite_Errors(t *testing.T) {
 			memory:        memory[0:9], // iovs[0].offset (where to read "hi") is in memory, but truncated.
 			expectedErrno: ErrnoFault,
 			expectedLog: `
---> proxy.fd_write(fd=4,iovs=0,iovs_len=1,result.size=0)
-	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=0,iovs_len=1,result.size=0)
+--> proxy.fd_write(fd=4,iovs=0,iovs_len=1,result.nwritten=0)
+	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=0,iovs_len=1,result.nwritten=0)
 	<== EFAULT
 <-- 21
 `,
 		},
 		{
-			name:          "resultSize offset is outside memory",
-			fd:            fd,
-			memory:        memory,
-			resultSize:    uint32(len(memory)), // read was ok, but there wasn't enough memory to write the result.
-			expectedErrno: ErrnoFault,
+			name:           "resultNwritten offset is outside memory",
+			fd:             fd,
+			memory:         memory,
+			resultNwritten: uint32(len(memory)), // read was ok, but there wasn't enough memory to write the result.
+			expectedErrno:  ErrnoFault,
 			expectedLog: `
---> proxy.fd_write(fd=4,iovs=0,iovs_len=1,result.size=10)
-	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=0,iovs_len=1,result.size=10)
+--> proxy.fd_write(fd=4,iovs=0,iovs_len=1,result.nwritten=10)
+	==> wasi_snapshot_preview1.fd_write(fd=4,iovs=0,iovs_len=1,result.nwritten=10)
 	<== EFAULT
 <-- 21
 `,
@@ -2268,7 +2268,7 @@ func Test_fdWrite_Errors(t *testing.T) {
 			mod.Memory().(*wasm.MemoryInstance).Buffer = tc.memory
 
 			requireErrno(t, tc.expectedErrno, mod, fdWriteName, uint64(tc.fd), uint64(iovs), uint64(iovsCount),
-				uint64(tc.resultSize))
+				uint64(tc.resultNwritten))
 			require.Equal(t, tc.expectedLog, "\n"+log.String())
 		})
 	}
@@ -2396,8 +2396,8 @@ func Test_pathFilestatGet(t *testing.T) {
 			fd:            math.MaxUint32,
 			expectedErrno: ErrnoBadf,
 			expectedLog: `
---> proxy.path_filestat_get(fd=4294967295,flags=0,path=1,path_len=0,result.buf=0)
-	==> wasi_snapshot_preview1.path_filestat_get(fd=4294967295,flags=0,path=1,path_len=0,result.buf=0)
+--> proxy.path_filestat_get(fd=-1,flags=0,path=1,path_len=0,result.buf=0)
+	==> wasi_snapshot_preview1.path_filestat_get(fd=-1,flags=0,path=1,path_len=0,result.buf=0)
 	<== EBADF
 <-- 8
 `,
diff --git a/internal/engine/compiler/engine_test.go b/internal/engine/compiler/engine_test.go
index 1fa91c83..d6ed42a4 100644
--- a/internal/engine/compiler/engine_test.go
+++ b/internal/engine/compiler/engine_test.go
@@ -85,7 +85,7 @@ func TestCompiler_ModuleEngine_Call_Errors(t *testing.T) {
 	// TODO: Currently, the listener doesn't get notified on errors as they are
 	// implemented with panic. This means the end hooks aren't make resulting
 	// in dangling logs like this:
-	//	==> host.host_div_by(4294967295)
+	//	==> host.host_div_by(-1)
 	// instead of seeing a return like
 	//	<== DivByZero
 	require.Equal(t, `
@@ -96,8 +96,8 @@ func TestCompiler_ModuleEngine_Call_Errors(t *testing.T) {
 --> imported.div_by.wasm(0)
 --> imported.div_by.wasm(1)
 <-- 1
---> imported.call->div_by.go(4294967295)
-	==> host.div_by.go(4294967295)
+--> imported.call->div_by.go(-1)
+	==> host.div_by.go(-1)
 --> imported.call->div_by.go(1)
 	==> host.div_by.go(1)
 	<== 1
@@ -111,9 +111,9 @@ func TestCompiler_ModuleEngine_Call_Errors(t *testing.T) {
 		<== 1
 	<-- 1
 <-- 1
---> importing.call_import->call->div_by.go(4294967295)
-	--> imported.call->div_by.go(4294967295)
-		==> host.div_by.go(4294967295)
+--> importing.call_import->call->div_by.go(-1)
+	--> imported.call->div_by.go(-1)
+		==> host.div_by.go(-1)
 --> importing.call_import->call->div_by.go(1)
 	--> imported.call->div_by.go(1)
 		==> host.div_by.go(1)
diff --git a/internal/engine/interpreter/interpreter_test.go b/internal/engine/interpreter/interpreter_test.go
index 8ea6d0dd..55e95372 100644
--- a/internal/engine/interpreter/interpreter_test.go
+++ b/internal/engine/interpreter/interpreter_test.go
@@ -124,7 +124,7 @@ func TestInterpreter_ModuleEngine_Call_Errors(t *testing.T) {
 	// TODO: Currently, the listener doesn't get notified on errors as they are
 	// implemented with panic. This means the end hooks aren't make resulting
 	// in dangling logs like this:
-	//	==> host.host_div_by(4294967295)
+	//	==> host.host_div_by(-1)
 	// instead of seeing a return like
 	//	<== DivByZero
 	require.Equal(t, `
@@ -135,8 +135,8 @@ func TestInterpreter_ModuleEngine_Call_Errors(t *testing.T) {
 --> imported.div_by.wasm(0)
 --> imported.div_by.wasm(1)
 <-- 1
---> imported.call->div_by.go(4294967295)
-	==> host.div_by.go(4294967295)
+--> imported.call->div_by.go(-1)
+	==> host.div_by.go(-1)
 --> imported.call->div_by.go(1)
 	==> host.div_by.go(1)
 	<== 1
@@ -150,9 +150,9 @@ func TestInterpreter_ModuleEngine_Call_Errors(t *testing.T) {
 		<== 1
 	<-- 1
 <-- 1
---> importing.call_import->call->div_by.go(4294967295)
-	--> imported.call->div_by.go(4294967295)
-		==> host.div_by.go(4294967295)
+--> importing.call_import->call->div_by.go(-1)
+	--> imported.call->div_by.go(-1)
+		==> host.div_by.go(-1)
 --> importing.call_import->call->div_by.go(1)
 	--> imported.call->div_by.go(1)
 		==> host.div_by.go(1)
diff --git a/internal/integration_test/bench/bench_test.go b/internal/integration_test/bench/bench_test.go
index 34c8f82e..3d206abc 100644
--- a/internal/integration_test/bench/bench_test.go
+++ b/internal/integration_test/bench/bench_test.go
@@ -125,10 +125,11 @@ func runInitializationConcurrentBench(b *testing.B, r wazero.Runtime) {
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		go func(name string) {
-			_, err := r.InstantiateModule(testCtx, compiled, config.WithName(name))
+			m, err := r.InstantiateModule(testCtx, compiled, config.WithName(name))
 			if err != nil {
 				b.Error(err)
 			}
+			m.Close(testCtx)
 			wg.Done()
 		}(strconv.Itoa(i))
 	}
diff --git a/internal/wasm/namespace_test.go b/internal/wasm/namespace_test.go
index 87ffb46f..551100c2 100644
--- a/internal/wasm/namespace_test.go
+++ b/internal/wasm/namespace_test.go
@@ -47,8 +47,8 @@ func TestNamespace_deleteModule(t *testing.T) {
 
 		// Leaves the other module alone
 		require.Equal(t, map[string]*ModuleInstance{m1.Name: m1}, ns.modules)
-		require.Equal(t, map[string]struct{}{m1.Name: {}}, ns.moduleNamesSet)
-		require.Equal(t, []string{m1.Name}, ns.moduleNamesList)
+		require.Equal(t, map[string]*nameListNode{m1.Name: {name: m1.Name}}, ns.moduleNamesSet)
+		require.Equal(t, &nameListNode{name: m1.Name}, ns.moduleNamesList)
 	})
 
 	t.Run("ok if missing", func(t *testing.T) {
@@ -60,7 +60,7 @@ func TestNamespace_deleteModule(t *testing.T) {
 
 		require.Zero(t, len(ns.modules))
 		require.Zero(t, len(ns.moduleNamesSet))
-		require.Zero(t, len(ns.moduleNamesList))
+		require.Nil(t, ns.moduleNamesList)
 	})
 }
 
@@ -93,24 +93,27 @@ func TestNamespace_requireModules(t *testing.T) {
 }
 
 func TestNamespace_requireModuleName(t *testing.T) {
-	ns := &Namespace{moduleNamesSet: map[string]struct{}{}}
+	ns := &Namespace{moduleNamesSet: map[string]*nameListNode{}}
 
 	t.Run("first", func(t *testing.T) {
 		err := ns.requireModuleName("m1")
 		require.NoError(t, err)
 
 		// Ensure it adds the module name, and doesn't impact the module list.
-		require.Equal(t, []string{"m1"}, ns.moduleNamesList)
-		require.Equal(t, map[string]struct{}{"m1": {}}, ns.moduleNamesSet)
+		require.Equal(t, &nameListNode{name: "m1"}, ns.moduleNamesList)
+		require.Equal(t, map[string]*nameListNode{"m1": {name: "m1"}}, ns.moduleNamesSet)
 		require.Zero(t, len(ns.modules))
 	})
 	t.Run("second", func(t *testing.T) {
 		err := ns.requireModuleName("m2")
 		require.NoError(t, err)
+		m2Node := &nameListNode{name: "m2"}
+		m1Node := &nameListNode{name: "m1", prev: m2Node}
+		m2Node.next = m1Node
 
 		// Appends in order.
-		require.Equal(t, []string{"m1", "m2"}, ns.moduleNamesList)
-		require.Equal(t, map[string]struct{}{"m1": {}, "m2": {}}, ns.moduleNamesSet)
+		require.Equal(t, m2Node, ns.moduleNamesList)
+		require.Equal(t, map[string]*nameListNode{"m1": m1Node, "m2": m2Node}, ns.moduleNamesSet)
 	})
 	t.Run("existing", func(t *testing.T) {
 		err := ns.requireModuleName("m2")
@@ -165,7 +168,7 @@ func TestNamespace_CloseWithExitCode(t *testing.T) {
 			// Namespace state zeroed
 			require.Zero(t, len(ns.modules))
 			require.Zero(t, len(ns.moduleNamesSet))
-			require.Zero(t, len(ns.moduleNamesList))
+			require.Nil(t, ns.moduleNamesList)
 		})
 	}
 
@@ -191,7 +194,7 @@ func TestNamespace_CloseWithExitCode(t *testing.T) {
 		// Namespace state zeroed
 		require.Zero(t, len(ns.modules))
 		require.Zero(t, len(ns.moduleNamesSet))
-		require.Zero(t, len(ns.moduleNamesList))
+		require.Nil(t, ns.moduleNamesList)
 	})
 }
 
@@ -217,7 +220,9 @@ func newTestNamespace() (*Namespace, *ModuleInstance, *ModuleInstance) {
 	m2.CallCtx = NewCallContext(ns, m2, nil)
 
 	ns.modules = map[string]*ModuleInstance{m1.Name: m1, m2.Name: m2}
-	ns.moduleNamesSet = map[string]struct{}{m1.Name: {}, m2.Name: {}}
-	ns.moduleNamesList = []string{m1.Name, m2.Name}
+	node1 := &nameListNode{name: m1.Name}
+	node2 := &nameListNode{name: m2.Name, next: node1}
+	ns.moduleNamesSet = map[string]*nameListNode{m1.Name: node1, m2.Name: node2}
+	ns.moduleNamesList = node2
 	return ns, m1, m2
 }