Repository: tetratelabs/wazero
Pull request #808 (2022-09-19 07:29:40)

wasi: stubs sock_accept and removes things removed from WASI
This catches up with latest WASI drift.



Patch:
diff --git a/imports/wasi_snapshot_preview1/clock.go b/imports/wasi_snapshot_preview1/clock.go
index c4297ea0..22d5500f 100644
--- a/imports/wasi_snapshot_preview1/clock.go
+++ b/imports/wasi_snapshot_preview1/clock.go
@@ -19,10 +19,8 @@ const (
 	clockIDRealtime = iota
 	// clockIDMonotonic is the name ID named "monotonic" like sys.Nanotime
 	clockIDMonotonic
-	// clockIDProcessCputime is the unsupported "process_cputime_id"
-	clockIDProcessCputime
-	// clockIDThreadCputime is the unsupported "thread_cputime_id"
-	clockIDThreadCputime
+	// Note: clockIDProcessCputime and clockIDThreadCputime were removed by
+	// WASI maintainers: https://github.com/WebAssembly/wasi-libc/pull/294
 )
 
 // clockResGet is the WASI function named functionClockResGet that returns the
@@ -65,11 +63,6 @@ var clockResGet = wasm.NewGoFunc(
 			resolution = uint64(sysCtx.WalltimeResolution())
 		case clockIDMonotonic:
 			resolution = uint64(sysCtx.NanotimeResolution())
-		case clockIDProcessCputime, clockIDThreadCputime:
-			// Similar to many other runtimes, we only support realtime and
-			// monotonic clocks. Other types are slated to be removed from the next
-			// version of WASI.
-			return ErrnoNotsup
 		default:
 			return ErrnoInval
 		}
@@ -125,11 +118,6 @@ var clockTimeGet = wasm.NewGoFunc(
 			val = (uint64(sec) * uint64(time.Second.Nanoseconds())) + uint64(nsec)
 		case clockIDMonotonic:
 			val = uint64(sysCtx.Nanotime(ctx))
-		case clockIDProcessCputime, clockIDThreadCputime:
-			// Similar to many other runtimes, we only support realtime and
-			// monotonic clocks. Other types are slated to be removed from the next
-			// version of WASI.
-			return ErrnoNotsup
 		default:
 			return ErrnoInval
 		}
diff --git a/imports/wasi_snapshot_preview1/errno.go b/imports/wasi_snapshot_preview1/errno.go
index 6113e0a0..9bf22cda 100644
--- a/imports/wasi_snapshot_preview1/errno.go
+++ b/imports/wasi_snapshot_preview1/errno.go
@@ -9,7 +9,8 @@ import (
 // # Notes
 //
 //   - This is not always an error, as ErrnoSuccess is a valid code.
-//   - Codes are defined even when not relevant to WASI for use in higher-level libraries or alignment with POSIX.
+//   - Codes are defined even when not relevant to WASI for use in higher-level
+//     libraries or alignment with POSIX.
 //
 // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-errno-enumu16 and
 // https://linux.die.net/man/3/errno
@@ -176,6 +177,7 @@ const (
 	ErrnoTxtbsy
 	// ErrnoXdev Cross-device link.
 	ErrnoXdev
-	// ErrnoNotcapable Extension: Capabilities insufficient.
-	ErrnoNotcapable
+
+	// Note: ErrnoNotcapable was removed by WASI maintainers.
+	// See https://github.com/WebAssembly/wasi-libc/pull/294
 )
diff --git a/imports/wasi_snapshot_preview1/fs.go b/imports/wasi_snapshot_preview1/fs.go
index b05dabe9..861ebb50 100644
--- a/imports/wasi_snapshot_preview1/fs.go
+++ b/imports/wasi_snapshot_preview1/fs.go
@@ -119,11 +119,11 @@ var fdDatasync = stubFunction(
 //   - ErrnoFault: `resultFdstat` points to an offset out of memory
 //
 // fdstat byte layout is 24-byte size, with the following fields:
-//   - fs_filetype 1 byte, to indicate the file type
-//   - fs_flags 2 bytes, to indicate the file descriptor flag
+//   - fs_filetype 1 byte: the file type
+//   - fs_flags 2 bytes: the file descriptor flag
 //   - 5 pad bytes
-//   - fs_right_base 8 bytes, to indicate the current rights of the fd
-//   - fs_right_inheriting 8 bytes, to indicate the maximum rights of the fd
+//   - fs_right_base 8 bytes: ignored as rights were removed from WASI.
+//   - fs_right_inheriting 8 bytes: ignored as rights were removed from WASI.
 //
 // For example, with a file corresponding with `fd` was a directory (=3) opened
 // with `fd_read` right (=1) and no fs_flags (=0), parameter resultFdstat=1,
@@ -164,12 +164,9 @@ var fdFdstatSetFlags = stubFunction(
 	[]string{"fd", "flags"},
 )
 
-// fdFdstatSetRights is the WASI function named functionFdFdstatSetRights which
-// adjusts the rights associated with a file descriptor.
+// fdFdstatSetRights will not be implemented as rights were removed from WASI.
 //
-// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_fdstat_set_rightsfd-fd-fs_rights_base-rights-fs_rights_inheriting-rights---errno
-//
-// Note: This will never be implemented per https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844
+// See https://github.com/bytecodealliance/wasmtime/pull/4666
 var fdFdstatSetRights = stubFunction(
 	functionFdFdstatSetRights,
 	[]wasm.ValueType{i32, i64, i64},
@@ -696,8 +693,8 @@ var pathLink = stubFunction(
 //   - path: offset in api.Memory to read the path string from
 //   - pathLen: length of `path`
 //   - oFlags: open flags to indicate the method by which to open the file
-//   - fsRightsBase: rights of the newly created file descriptor for `path`
-//   - fsRightsInheriting: rights of the file descriptors derived from the newly
+//   - fsRightsBase: ignored as rights were removed from WASI.
+//   - fsRightsInheriting: ignored as rights were removed from WASI.
 //     created file descriptor for `path`
 //   - fdFlags: file descriptor flags
 //   - resultOpenedFd: offset in api.Memory to write the newly created file
@@ -737,14 +734,13 @@ var pathLink = stubFunction(
 // # Notes
 //   - This is similar to `openat` in POSIX. https://linux.die.net/man/3/openat
 //   - The returned file descriptor is not guaranteed to be the lowest-number
-//   - Rights will never be implemented per https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844
 //
 // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#path_open
 var pathOpen = wasm.NewGoFunc(
 	functionPathOpen, functionPathOpen,
 	[]string{"fd", "dirflags", "path", "path_len", "oflags", "fs_rights_base", "fs_rights_inheriting", "fdflags", "result.opened_fd"},
-	func(ctx context.Context, mod api.Module, fd, dirflags, pathPtr, pathLen, oflags uint32, fsRightsBase,
-		fsRightsInheriting uint64, fdflags, resultOpenedFd uint32) (errno Errno) {
+	func(ctx context.Context, mod api.Module, fd, dirflags, pathPtr, pathLen, oflags uint32, _, _ uint64,
+		fdflags, resultOpenedFd uint32) (errno Errno) {
 		sysCtx := mod.(*wasm.CallContext).Sys
 		fsc := sysCtx.FS(ctx)
 		if _, ok := fsc.OpenedFile(ctx, fd); !ok {
diff --git a/imports/wasi_snapshot_preview1/proc.go b/imports/wasi_snapshot_preview1/proc.go
index 1026d172..9e656d1b 100644
--- a/imports/wasi_snapshot_preview1/proc.go
+++ b/imports/wasi_snapshot_preview1/proc.go
@@ -36,8 +36,7 @@ var procExit = wasm.NewGoFunc(
 	},
 )
 
-// procRaise is the WASI function named functionProcRaise which sends a signal
-// to the process of the calling thread.
+// procRaise is stubbed and will never be supported, as it was removed.
 //
-// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-proc_raisesig-signal---errno
+// See https://github.com/WebAssembly/WASI/pull/136
 var procRaise = stubFunction(functionProcRaise, []wasm.ValueType{i32}, []string{"sig"})
diff --git a/imports/wasi_snapshot_preview1/sock.go b/imports/wasi_snapshot_preview1/sock.go
index 55a847b3..90147168 100644
--- a/imports/wasi_snapshot_preview1/sock.go
+++ b/imports/wasi_snapshot_preview1/sock.go
@@ -3,11 +3,23 @@ package wasi_snapshot_preview1
 import "github.com/tetratelabs/wazero/internal/wasm"
 
 const (
+	functionSockAccept   = "sock_accept"
 	functionSockRecv     = "sock_recv"
 	functionSockSend     = "sock_send"
 	functionSockShutdown = "sock_shutdown"
 )
 
+// sockAccept is the WASI function named functionSockAccept which accepts a new
+// incoming connection.
+//
+// See: https://github.com/WebAssembly/WASI/blob/0ba0c5e2e37625ca5a6d3e4255a998dfaa3efc52/phases/snapshot/docs.md#sock_accept
+// and https://github.com/WebAssembly/WASI/pull/458
+var sockAccept = stubFunction(
+	functionSockAccept,
+	[]wasm.ValueType{i32, i32, i32},
+	[]string{"fd", "flags", "result.fd"},
+)
+
 // sockRecv is the WASI function named functionSockRecv which receives a
 // message from a socket.
 //
diff --git a/imports/wasi_snapshot_preview1/wasi.go b/imports/wasi_snapshot_preview1/wasi.go
index 7ec7841e..0e46c1e8 100644
--- a/imports/wasi_snapshot_preview1/wasi.go
+++ b/imports/wasi_snapshot_preview1/wasi.go
@@ -110,7 +110,8 @@ func (b *builder) Instantiate(ctx context.Context, ns wazero.Namespace) (api.Clo
 // exportFunctions adds all go functions that implement wasi.
 // These should be exported in the module named ModuleName.
 func exportFunctions(builder wazero.ModuleBuilder) {
-	// Note:se are ordered per spec for consistency even if the resulting map can't guarantee that.
+	// Note: these are ordered per spec for consistency even if the resulting
+	// map can't guarantee that.
 	// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#functions
 	builder.ExportFunction(argsGet.Name, argsGet)
 	builder.ExportFunction(argsSizesGet.Name, argsSizesGet)
@@ -154,6 +155,7 @@ func exportFunctions(builder wazero.ModuleBuilder) {
 	builder.ExportFunction(procRaise.Name, procRaise)
 	builder.ExportFunction(schedYield.Name, schedYield)
 	builder.ExportFunction(randomGet.Name, randomGet)
+	builder.ExportFunction(sockAccept.Name, sockAccept)
 	builder.ExportFunction(sockRecv.Name, sockRecv)
 	builder.ExportFunction(sockSend.Name, sockSend)
 	builder.ExportFunction(sockShutdown.Name, sockShutdown)
diff --git a/site/content/languages/tinygo.md b/site/content/languages/tinygo.md
index f920223c..c8744877 100644
--- a/site/content/languages/tinygo.md
+++ b/site/content/languages/tinygo.md
@@ -115,7 +115,7 @@ in more, see [System Calls](#system-calls).
 ## Memory
 
 When TinyGo compiles go into wasm, it configures the WebAssembly linear memory
-to an initial size of 2 pages (16KB), and marks a position in that memory as
+to an initial size of 2 pages (128KB), and marks a position in that memory as
 the heap base. All memory beyond that is used for the Go heap.
 
 Allocations within Go (compiled to `%.wasm`) are managed as one would expect.
diff --git a/site/content/specs.md b/site/content/specs.md
index 430e267f..9cd82eff 100644
--- a/site/content/specs.md
+++ b/site/content/specs.md
@@ -66,8 +66,9 @@ any working drafts as a result of their work. WASI's last stable point was
 
 Some functions in this tag are used in practice while some others are not known
 to be used at all. Further confusion exists because some compilers, like
-GrainLang, import functions not used. Finally, [wasi_snapshot_preview1][4]
-includes features such as "rights" that [will be removed][13].
+GrainLang, import functions not used. Finally, some functions were added and
+removed after the git tag. For example, [`proc_raise`][13] was removed and
+[`sock_accept`][15] added.
 
 For all of these reasons, wazero will not implement all WASI features, just to
 complete the below chart. If you desire something not yet implemented, please
@@ -91,7 +92,7 @@ your use case (ex which language you are using to compile, a.k.a. target Wasm).
 | fd_datasync             |   ❌    |                 |
 | fd_fdstat_get           |   ✅    |          TinyGo |
 | fd_fdstat_set_flags     |   ❌    |                 |
-| fd_fdstat_set_rights    |   ❌    |                 |
+| fd_fdstat_set_rights    |   💀   |                 |
 | fd_filestat_get         |   ❌    |                 |
 | fd_filestat_set_size    |   ❌    |                 |
 | fd_filestat_set_times   |   ❌    |                 |
@@ -118,13 +119,16 @@ your use case (ex which language you are using to compile, a.k.a. target Wasm).
 | path_unlink_file        |   ❌    |                 |
 | poll_oneoff             |   ✅    | Rust,TinyGo,Zig |
 | proc_exit               |   ✅    |  AssemblyScript |
-| proc_raise              |   ❌    |                 |
+| proc_raise              |   💀   |                 |
 | sched_yield             |   ❌    |                 |
 | random_get              |   ✅    |                 |
+| sock_accept             |   ❌    |                 |
 | sock_recv               |   ❌    |                 |
 | sock_send               |   ❌    |                 |
 | sock_shutdown           |   ❌    |                 |
 
+Note: 💀 means the function was later removed from WASI.
+
 </p>
 </details>
 
@@ -139,5 +143,6 @@ your use case (ex which language you are using to compile, a.k.a. target Wasm).
 [10]: https://github.com/WebAssembly/proposals
 [11]: https://github.com/WebAssembly/proposals/blob/main/finished-proposals.md
 [12]: https://www.w3.org/community/webassembly/
-[13]: https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844
+[13]: https://github.com/WebAssembly/WASI/pull/136
 [14]: https://github.com/WebAssembly/spec/tree/d39195773112a22b245ffbe864bab6d1182ccb06/test/core
+[15]: https://github.com/WebAssembly/WASI/pull/458


Test patch:
diff --git a/imports/wasi_snapshot_preview1/clock_test.go b/imports/wasi_snapshot_preview1/clock_test.go
index 24320a5e..1021eefb 100644
--- a/imports/wasi_snapshot_preview1/clock_test.go
+++ b/imports/wasi_snapshot_preview1/clock_test.go
@@ -86,23 +86,23 @@ func Test_clockResGet_Unsupported(t *testing.T) {
 		{
 			name:          "process cputime",
 			clockID:       2,
-			expectedErrno: ErrnoNotsup,
+			expectedErrno: ErrnoInval,
 			expectedLog: `
 --> proxy.clock_res_get(id=2,result.resolution=1)
 	==> wasi_snapshot_preview1.clock_res_get(id=2,result.resolution=1)
-	<== ENOTSUP
-<-- (58)
+	<== EINVAL
+<-- (28)
 `,
 		},
 		{
 			name:          "thread cputime",
 			clockID:       3,
-			expectedErrno: ErrnoNotsup,
+			expectedErrno: ErrnoInval,
 			expectedLog: `
 --> proxy.clock_res_get(id=3,result.resolution=1)
 	==> wasi_snapshot_preview1.clock_res_get(id=3,result.resolution=1)
-	<== ENOTSUP
-<-- (58)
+	<== EINVAL
+<-- (28)
 `,
 		},
 		{
@@ -204,23 +204,23 @@ func Test_clockTimeGet_Unsupported(t *testing.T) {
 		{
 			name:          "process cputime",
 			clockID:       2,
-			expectedErrno: ErrnoNotsup,
+			expectedErrno: ErrnoInval,
 			expectedLog: `
 --> proxy.clock_time_get(id=2,precision=0,result.timestamp=1)
 	==> wasi_snapshot_preview1.clock_time_get(id=2,precision=0,result.timestamp=1)
-	<== ENOTSUP
-<-- (58)
+	<== EINVAL
+<-- (28)
 `,
 		},
 		{
 			name:          "thread cputime",
 			clockID:       3,
-			expectedErrno: ErrnoNotsup,
+			expectedErrno: ErrnoInval,
 			expectedLog: `
 --> proxy.clock_time_get(id=3,precision=0,result.timestamp=1)
 	==> wasi_snapshot_preview1.clock_time_get(id=3,precision=0,result.timestamp=1)
-	<== ENOTSUP
-<-- (58)
+	<== EINVAL
+<-- (28)
 `,
 		},
 		{
diff --git a/imports/wasi_snapshot_preview1/fs_test.go b/imports/wasi_snapshot_preview1/fs_test.go
index a98c7878..bd2f38c7 100644
--- a/imports/wasi_snapshot_preview1/fs_test.go
+++ b/imports/wasi_snapshot_preview1/fs_test.go
@@ -1126,9 +1126,8 @@ func Test_pathOpen(t *testing.T) {
 	pathPtr := uint32(1)
 	pathLen := uint32(len(pathName))
 	oflags := uint32(0)
-	// rights are ignored per https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844
-	fsRightsBase := uint64(1)
-	fsRightsInheriting := uint64(2)
+	fsRightsBase := uint64(1)       // ignored: rights were removed from WASI.
+	fsRightsInheriting := uint64(2) // ignored: rights were removed from WASI.
 	fdflags := uint32(0)
 	resultOpenedFd := uint32(len(initialMemory) + 1)
 
diff --git a/imports/wasi_snapshot_preview1/sock_test.go b/imports/wasi_snapshot_preview1/sock_test.go
index 6cde62a5..d21e8490 100644
--- a/imports/wasi_snapshot_preview1/sock_test.go
+++ b/imports/wasi_snapshot_preview1/sock_test.go
@@ -6,6 +6,17 @@ import (
 	"github.com/tetratelabs/wazero/internal/testing/require"
 )
 
+// Test_sockAccept only tests it is stubbed for GrainLang per #271
+func Test_sockAccept(t *testing.T) {
+	log := requireErrnoNosys(t, functionSockAccept, 0, 0, 0)
+	require.Equal(t, `
+--> proxy.sock_accept(fd=0,flags=0,result.fd=0)
+	--> wasi_snapshot_preview1.sock_accept(fd=0,flags=0,result.fd=0)
+	<-- ENOSYS
+<-- (52)
+`, log)
+}
+
 // Test_sockRecv only tests it is stubbed for GrainLang per #271
 func Test_sockRecv(t *testing.T) {
 	log := requireErrnoNosys(t, functionSockRecv, 0, 0, 0, 0, 0, 0)