gasm

module
v0.0.0-...-1228a4d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 15, 2021 License: MIT

README ¶

gasm

CircleCI MIT License

A minimal implementation of v1 WASM spec compatible virtual machine purely written in go. The vm can be embedded in your go program without any dependency like cgo, and enables Gophers to write wasm host environments easily.

The vm should be used only for providing sandbox environments embedded in your Go program since we have not implemented validation of wasm binary.

The implementation is quite straightforward and I hope this code would be a good starting point for novices to learn WASM spec.

examples

Full examples can be found at: https://github.com/mathetake/gasm/tree/master/examples

call exported function from host
func Test_fibonacci(t *testing.T) {
	buf, _ := ioutil.ReadFile("wasm/fibonacci.wasm")
	mod, _ := wasm.DecodeModule(bytes.NewBuffer(buf))
	vm, _ := wasm.NewVM(mod, wasi.New().Modules())

	for _, c := range []struct {
		in, exp int32
	}{
		{in: 20, exp: 6765},
		{in: 10, exp: 55},
		{in: 5, exp: 5},
	} {
		ret, _, _ := vm.ExecExportedFunction("fib", uint64(c.in))
		require.Equal(t, c.exp, int32(ret[0]))
	}
}
call host function from WASM module

func Test_hostFunc(t *testing.T) {
	buf, _ := ioutil.ReadFile("wasm/host_func.wasm")
	mod, _ := wasm.DecodeModule(bytes.NewBuffer(buf))

	var cnt uint64  // to be incremented as hostFunc is called

	// host functions must be defined in the form of `Virtual Machine closure` generators
	// in order to access the VM state to get things done
	hostFunc := func(*wasm.VirtualMachine) reflect.Value {
		return reflect.ValueOf(func() {
			cnt++
		})
	}

	builder := hostfunc.NewModuleBuilderWith(wasi.New().Modules())
	builder.MustSetFunction("env", "host_func", hostFunc)
	vm, _ := wasm.NewVM(mod, builder.Done())

	for _, exp := range []uint64{5, 10, 15} {
		vm.ExecExportedFunction("call_host_func", exp)
		require.Equal(t, exp, cnt)
		cnt = 0
	}
}

🚧 WASI support 🚧

WebAssembly System Interface (WASI) is partly supported in wasi package. Currently these methods are implemented:

  • fd_write
  • fd_prestat_get
  • fd_prestat_dir_name
  • path_open
  • fd_read
  • fd_close

By default, WASI uses the host process's Stdin, Stdout and Stderr and doesn't preopen any directories, but that can be changed with functional options.

vm, err := wasm.NewVM(mod, wasi.New(
	wasi.Stdin(myReader),
	wasi.Stdout(myWriter),
	wasi.Stderr(myErrWriter),
	wasi.Preopen(".", wasi.DirFS(".")),
).Modules())
if err != nil {
	panic(err)
}

if err := vm.ExecExportedFunction("_start"); err != nil {
	panic(err)
}

If you want to provide an in-memory file system to the wasm binary, you can do so with wasi.MemFS().

references

Directories ¶

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL