Skip to content

Commit

Permalink
Removes GOOS=js related leftovers (tetratelabs#2193)
Browse files Browse the repository at this point in the history
Signed-off-by: Takeshi Yoneda <[email protected]>
  • Loading branch information
mathetake authored Apr 22, 2024
1 parent 5a9cb5a commit 7ad2b70
Show file tree
Hide file tree
Showing 21 changed files with 62 additions and 691 deletions.
23 changes: 5 additions & 18 deletions RATIONALE.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,8 +568,7 @@ In short, wazero defined system configuration in `ModuleConfig`, not a WASI type
one spec to another with minimal impact. This has other helpful benefits, as centralized resources are simpler to close
coherently (ex via `Module.Close`).

In reflection, this worked well as more ABI became usable in wazero. For example, `GOOS=js GOARCH=wasm` code uses the
same `ModuleConfig` (and `FSConfig`) WASI uses, and in compatible ways.
In reflection, this worked well as more ABI became usable in wazero.

### Background on `ModuleConfig` design

Expand Down Expand Up @@ -753,8 +752,7 @@ independent of the root file system. This intended to help separate concerns
like mutability of files, but it didn't work and was removed.

Compilers that target wasm act differently with regard to the working
directory. For example, while `GOOS=js` uses host functions to track the
working directory, WASI host functions do not. wasi-libc, used by TinyGo,
directory. For example, wasi-libc, used by TinyGo,
tracks working directory changes in compiled wasm instead: initially "/" until
code calls `chdir`. Zig assumes the first pre-opened file descriptor is the
working directory.
Expand Down Expand Up @@ -829,21 +827,14 @@ The main reason is that `os.DirFS` is a virtual filesystem abstraction while
WASI is an abstraction over syscalls. For example, the signature of `fs.Open`
does not permit use of flags. This creates conflict on what default behaviors
to take when Go implemented `os.DirFS`. On the other hand, `path_open` can pass
flags, and in fact tests require them to be honored in specific ways. This
extends beyond WASI as even `GOOS=js GOARCH=wasm` compiled code requires
certain flags passed to `os.OpenFile` which are impossible to pass due to the
signature of `fs.FS`.
flags, and in fact tests require them to be honored in specific ways.

This conflict requires us to choose what to be more compatible with, and which
type of user to surprise the least. We assume there will be more developers
compiling code to wasm than developers of custom filesystem plugins, and those
compiling code to wasm will be better served if we are compatible with WASI.
Hence on conflict, we prefer WASI behavior vs the behavior of `os.DirFS`.

Meanwhile, it is possible that Go will one day compile to `GOOS=wasi` in
addition to `GOOS=js`. When there is shared stake in WASI, we expect gaps like
these to be easier to close.

See https://github.com/WebAssembly/wasi-testsuite
See https://github.com/golang/go/issues/58141

Expand Down Expand Up @@ -1205,10 +1196,7 @@ See https://gruss.cc/files/fantastictimers.pdf for an example attacks.
### Why does fake time increase on reading?

Both the fake nanotime and walltime increase by 1ms on reading. Particularly in
the case of nanotime, this prevents spinning. For example, when Go compiles
`time.Sleep` using `GOOS=js GOARCH=wasm`, nanotime is used in a loop. If that
never increases, the gouroutine is mistaken for being busy. This would be worse
if a compiler implement sleep using nanotime, yet doesn't check for spinning!
the case of nanotime, this prevents spinning.

### Why not `time.Clock`?

Expand Down Expand Up @@ -1266,8 +1254,7 @@ pub fn main() !void {
```

Besides Zig, this is also the case with TinyGo (`-target=wasi`) and Rust
(`--target wasm32-wasi`). This isn't the case with Go (`GOOS=js GOARCH=wasm`),
though. In the latter case, wasm loops on `sys.Nanotime`.
(`--target wasm32-wasi`).

We decided to expose `sys.Nanosleep` to allow overriding the implementation
used in the common case, even if it isn't used by Go, because this gives an
Expand Down
16 changes: 0 additions & 16 deletions cmd/wazero/Dockerfile

This file was deleted.

13 changes: 0 additions & 13 deletions cmd/wazero/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,3 @@ wazero run calc.wasm 1 + 2
In addition to arguments, the WebAssembly binary has access to stdout, stderr,
and stdin.


### Docker / Podman

wazero doesn't currently publish binaries, but you can make your own with our
example [Dockerfile](Dockerfile). It should amount to about 4.5MB total.

```bash
# build the image
$ docker build -t wazero:latest -f Dockerfile .
# volume mount wasi or GOOS=js wasm you are interested in, and run it.
$ docker run -v $PWD/testdata/:/wasm wazero:latest /wasm/wasi_arg.wasm 1 2 3
wasi_arg.wasm123
```
2 changes: 1 addition & 1 deletion cmd/wazero/testdata/cat/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# GOOS=js GOARCH=wasm binaries are too huge to check-in
# GOOS=wasip1 GOARCH=wasm binaries are too huge to check-in
cat-go.wasm
35 changes: 0 additions & 35 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@ import (
"time"

"github.com/tetratelabs/wazero/api"
experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
"github.com/tetratelabs/wazero/internal/fstest"
"github.com/tetratelabs/wazero/internal/platform"
internalsys "github.com/tetratelabs/wazero/internal/sys"
"github.com/tetratelabs/wazero/internal/sysfs"
testfs "github.com/tetratelabs/wazero/internal/testing/fs"
"github.com/tetratelabs/wazero/internal/testing/require"
"github.com/tetratelabs/wazero/internal/wasm"
"github.com/tetratelabs/wazero/sys"
Expand Down Expand Up @@ -319,38 +316,6 @@ func TestModuleConfig_toSysContext(t *testing.T) {
}
},
},
{
name: "WithFS",
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
testFS := &testfs.FS{}
config := base.WithFS(testFS)
return config, func(t *testing.T, sys *internalsys.Context) {
rootfs := sys.FS().RootFS()
require.Equal(t, &sysfs.AdaptFS{FS: testFS}, rootfs)
}
},
},
{
name: "WithFS overwrites",
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
testFS, testFS2 := &testfs.FS{}, &testfs.FS{}
config := base.WithFS(testFS).WithFS(testFS2)
return config, func(t *testing.T, sys *internalsys.Context) {
rootfs := sys.FS().RootFS()
require.Equal(t, &sysfs.AdaptFS{FS: testFS2}, rootfs)
}
},
},
{
name: "WithFS nil",
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
config := base.WithFS(nil)
return config, func(t *testing.T, sys *internalsys.Context) {
rootfs := sys.FS().RootFS()
require.Equal(t, experimentalsys.UnimplementedFS{}, rootfs)
}
},
},
{
name: "WithRandSource",
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
Expand Down
5 changes: 2 additions & 3 deletions experimental/sys/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package sys
import "github.com/tetratelabs/wazero/sys"

// File is a writeable fs.File bridge backed by syscall functions needed for ABI
// including WASI and runtime.GOOS=js.
// including WASI.
//
// Implementations should embed UnimplementedFile for forward compatibility. Any
// unsupported method or parameter should return ENOSYS.
Expand All @@ -14,8 +14,7 @@ import "github.com/tetratelabs/wazero/sys"
// on success.
//
// Restricting to Errno matches current WebAssembly host functions,
// which are constrained to well-known error codes. For example, `GOOS=js` maps
// hard coded values and panics otherwise. More commonly, WASI maps syscall
// which are constrained to well-known error codes. For example, WASI maps syscall
// errors to u32 numeric values.
//
// # Notes
Expand Down
5 changes: 2 additions & 3 deletions experimental/sys/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
)

// FS is a writeable fs.FS bridge backed by syscall functions needed for ABI
// including WASI and runtime.GOOS=js.
// including WASI.
//
// Implementations should embed UnimplementedFS for forward compatibility. Any
// unsupported method or parameter should return ENO
Expand All @@ -18,8 +18,7 @@ import (
// on success.
//
// Restricting to Errno matches current WebAssembly host functions,
// which are constrained to well-known error codes. For example, `GOOS=js` maps
// hard coded values and panics otherwise. More commonly, WASI maps syscall
// which are constrained to well-known error codes. For example, WASI maps syscall
// errors to u32 numeric values.
//
// # Notes
Expand Down
2 changes: 1 addition & 1 deletion experimental/sysfs/sysfs.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Package sysfs includes a low-level filesystem interface and utilities needed
// for WebAssembly host functions (ABI) such as WASI and runtime.GOOS=js.
// for WebAssembly host functions (ABI) such as WASI.
//
// The name sysfs was chosen because wazero's public API has a "sys" package,
// which was named after https://github.com/golang/sys.
Expand Down
2 changes: 0 additions & 2 deletions fsconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ import (
// current directory prior to requesting files.
//
// More notes on `guestPath`
// - Go compiled with runtime.GOOS=js do not pay attention to this value.
// It only works with root mounts ("").
// - Working directories are typically tracked in wasm, though possible some
// relative paths are requested. For example, TinyGo may attempt to resolve
// a path "../.." in unit tests.
Expand Down
4 changes: 0 additions & 4 deletions imports/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,3 @@ Packages in this directory are sometimes well re-used, such as the case in
all target WebAssembly in a way that imports the same "wasi_snapshot_preview1"
module in the compiled `%.wasm` file. To support any of these, wazero users can
invoke `wasi_snapshot_preview1.Instantiate` on their `wazero.Runtime`.

Other times, host imports are either completely compiler-specific, such as the
case with `GOOS=js GOARCH=wasm`, or coexist alongside WASI, such as the case
with Emscripten.
47 changes: 29 additions & 18 deletions imports/wasi_snapshot_preview1/fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func Test_fdAllocate(t *testing.T) {
wazero.NewFSConfig().WithDirMount(tmpDir, "/"),
))
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)
defer r.Close(testCtx)

fd, errno := fsc.OpenFile(preopen, fileName, experimentalsys.O_RDWR, 0)
Expand Down Expand Up @@ -125,6 +125,12 @@ func Test_fdAllocate(t *testing.T) {
`, "\n"+log.String())
}

func getPreopen(t *testing.T, fsc *sys.FSContext) experimentalsys.FS {
preopen, ok := fsc.LookupFile(sys.FdPreopen)
require.True(t, ok)
return preopen.FS
}

func Test_fdClose(t *testing.T) {
// fd_close needs to close an open file descriptor. Open two files so that we can tell which is closed.
path1, path2 := "dir/-", "dir/a-"
Expand All @@ -133,7 +139,7 @@ func Test_fdClose(t *testing.T) {

// open both paths without using WASI
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)

fdToClose, errno := fsc.OpenFile(preopen, path1, experimentalsys.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)
Expand Down Expand Up @@ -237,7 +243,7 @@ func Test_fdFdstatGet(t *testing.T) {

// open both paths without using WASI
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)

// replace stdin with a fake TTY file.
// TODO: Make this easier once we have in-memory sys.File
Expand Down Expand Up @@ -488,7 +494,7 @@ func Test_fdFdstatSetFlagsWithTrunc(t *testing.T) {
defer r.Close(testCtx)

fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)

fd, errno := fsc.OpenFile(preopen, fileName, experimentalsys.O_RDWR|experimentalsys.O_CREAT|experimentalsys.O_EXCL|experimentalsys.O_TRUNC, 0o600)
require.EqualErrno(t, 0, errno)
Expand Down Expand Up @@ -533,7 +539,7 @@ func Test_fdFdstatSetFlags(t *testing.T) {
WithStderr(stderrW).
WithFSConfig(wazero.NewFSConfig().WithDirMount(tmpDir, "/")))
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)
defer r.Close(testCtx)

// First, O_CREAT the file with O_APPEND. We use O_EXCL because that
Expand Down Expand Up @@ -663,7 +669,7 @@ func Test_fdFilestatGet(t *testing.T) {

// open both paths without using WASI
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)

fileFD, errno := fsc.OpenFile(preopen, file, experimentalsys.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)
Expand Down Expand Up @@ -2075,7 +2081,7 @@ func Test_fdReaddir(t *testing.T) {
defer r.Close(testCtx)

fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)
fd := sys.FdPreopen + 1

tests := []struct {
Expand Down Expand Up @@ -2260,7 +2266,8 @@ func Test_fdReaddir_Rewind(t *testing.T) {

fsc := mod.(*wasm.ModuleInstance).Sys.FS()

fd, errno := fsc.OpenFile(fsc.RootFS(), ".", experimentalsys.O_RDONLY, 0)
preopen := getPreopen(t, fsc)
fd, errno := fsc.OpenFile(preopen, ".", experimentalsys.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)

mem := mod.Memory()
Expand Down Expand Up @@ -2307,7 +2314,7 @@ func Test_fdReaddir_Errors(t *testing.T) {
memLen := mod.Memory().Size()

fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)

fileFD, errno := fsc.OpenFile(preopen, "animals.txt", experimentalsys.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)
Expand Down Expand Up @@ -2523,7 +2530,7 @@ func Test_fdRenumber(t *testing.T) {
defer r.Close(testCtx)

fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)

// Sanity check of the file descriptor assignment.
fileFDAssigned, errno := fsc.OpenFile(preopen, "animals.txt", experimentalsys.O_RDONLY, 0)
Expand Down Expand Up @@ -2637,7 +2644,8 @@ func Test_fdSeek_Errors(t *testing.T) {
defer r.Close(testCtx)

fsc := mod.(*wasm.ModuleInstance).Sys.FS()
require.Zero(t, fsc.RootFS().Mkdir("dir", 0o0777))
preopen := getPreopen(t, fsc)
require.Zero(t, preopen.Mkdir("dir", 0o0777))
dirFD := requireOpenFD(t, mod, "dir")

memorySize := mod.Memory().Size()
Expand Down Expand Up @@ -3576,10 +3584,12 @@ func Test_pathFilestatSetTimes(t *testing.T) {
sys := mod.(*wasm.ModuleInstance).Sys
fsc := sys.FS()

preopen := getPreopen(t, fsc)

var oldSt sysapi.Stat_t
var errno experimentalsys.Errno
if tc.expectedErrno == wasip1.ErrnoSuccess {
oldSt, errno = fsc.RootFS().Stat(pathName)
oldSt, errno = preopen.Stat(pathName)
require.EqualErrno(t, 0, errno)
}

Expand All @@ -3591,7 +3601,7 @@ func Test_pathFilestatSetTimes(t *testing.T) {
return
}

newSt, errno := fsc.RootFS().Stat(pathName)
newSt, errno := preopen.Stat(pathName)
require.EqualErrno(t, 0, errno)

if platform.CompilerSupported() {
Expand Down Expand Up @@ -3630,7 +3640,8 @@ func Test_pathLink(t *testing.T) {
newDirPath := joinPath(tmpDir, newDirName)
require.NoError(t, os.MkdirAll(joinPath(tmpDir, newDirName), 0o700))
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
newFd, errno := fsc.OpenFile(fsc.RootFS(), newDirName, 0o600, 0)
preopen := getPreopen(t, fsc)
newFd, errno := fsc.OpenFile(preopen, newDirName, 0o600, 0)
require.EqualErrno(t, 0, errno)

mem := mod.Memory()
Expand Down Expand Up @@ -3981,7 +3992,7 @@ func writeAndCloseFile(t *testing.T, fsc *sys.FSContext, fd int32) []byte {

func requireOpenFD(t *testing.T, mod api.Module, path string) int32 {
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)

fd, errno := fsc.OpenFile(preopen, path, experimentalsys.O_RDONLY, 0)
require.EqualErrno(t, 0, errno)
Expand Down Expand Up @@ -4935,7 +4946,7 @@ func requireOpenFile(t *testing.T, tmpDir string, pathName string, data []byte,

mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().WithFSConfig(fsConfig))
fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)

fd, errno := fsc.OpenFile(preopen, pathName, oflags, 0)
require.EqualErrno(t, 0, errno)
Expand All @@ -4954,7 +4965,7 @@ func Test_fdReaddir_dotEntryHasARealInode(t *testing.T) {
mem := mod.Memory()

fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)

readDirTarget := "dir"
mem.Write(0, []byte(readDirTarget))
Expand Down Expand Up @@ -5007,7 +5018,7 @@ func Test_fdReaddir_opened_file_written(t *testing.T) {
mem := mod.Memory()

fsc := mod.(*wasm.ModuleInstance).Sys.FS()
preopen := fsc.RootFS()
preopen := getPreopen(t, fsc)

dirName := "dir"
dirPath := joinPath(tmpDir, dirName)
Expand Down
Loading

0 comments on commit 7ad2b70

Please sign in to comment.