diff --git a/README.md b/README.md index c2f25ce0..789931d5 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,20 @@ func main() { // Read a WebAssembly binary containing an exported "fac" function. // * Ex. (func (export "fac") (param i64) (result i64) ... - source, _ := os.ReadFile("./path/to/fac.wasm") + source, err := os.ReadFile("./path/to/fac.wasm") + if err != nil { + log.Panicln(err) + } + + // Create a new WebAssembly Runtime. + r := wazero.NewRuntime() + defer r.Close(ctx) // This closes everything this Runtime created. // Instantiate the module and return its exported functions - module, _ := wazero.NewRuntime().InstantiateModuleFromCode(ctx, source) - defer module.Close(ctx) + module, err := r.InstantiateModuleFromCode(ctx, source) + if err != nil { + log.Panicln(err) + } // Discover 7! is 5040 fmt.Println(module.ExportedFunction("fac").Call(ctx, 7)) @@ -57,15 +66,14 @@ For example, you can grant WebAssembly code access to your console by exporting a function written in Go. The below function can be imported into standard WebAssembly as the module "env" and the function name "log_i32". ```go -env, err := r.NewModuleBuilder("env"). +_, err := r.NewModuleBuilder("env"). ExportFunction("log_i32", func(v uint32) { fmt.Println("log_i32 >>", v) }). Instantiate(ctx) if err != nil { - log.Fatal(err) + log.Panicln(err) } -defer env.Close(ctx) ``` The WebAssembly community has [subgroups][4] which maintain work that may not @@ -78,12 +86,13 @@ bundles an implementation. That way, you don't have to write these functions. For example, here's how you can allow WebAssembly modules to read "/work/home/a.txt" as "/a.txt" or "./a.txt": ```go -wm, err := wasi.InstantiateSnapshotPreview1(ctx, r) -defer wm.Close(ctx) +_, err := wasi.InstantiateSnapshotPreview1(ctx, r) +if err != nil { + log.Panicln(err) +} config := wazero.NewModuleConfig().WithFS(os.DirFS("/work/home")) module, err := r.InstantiateModule(ctx, compiled, config) -defer module.Close(ctx) ... ``` diff --git a/api/wasm.go b/api/wasm.go index e82a7f51..43280b12 100644 --- a/api/wasm.go +++ b/api/wasm.go @@ -105,6 +105,7 @@ func ValueTypeName(t ValueType) string { // Module return functions exported in a module, post-instantiation. // +// Note: Closing the wazero.Runtime closes any Module it instantiated. // Note: This is an interface for decoupling, not third-party implementations. All implementations are in wazero. // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#external-types%E2%91%A0 type Module interface { diff --git a/builder.go b/builder.go index 2490455a..aa0d9f7d 100644 --- a/builder.go +++ b/builder.go @@ -15,6 +15,9 @@ import ( // Ex. Below defines and instantiates a module named "env" with one function: // // ctx := context.Background() +// r := wazero.NewRuntime() +// defer r.Close(ctx) // This closes everything this Runtime created. +// // hello := func() { // fmt.Fprintln(stdout, "hello!") // } @@ -29,10 +32,8 @@ import ( // Compile(ctx, wazero.NewCompileConfig()) // // env1, _ := r.InstantiateModule(ctx, compiled, wazero.NewModuleConfig().WithName("env.1")) -// defer env1.Close(ctx) // // env2, _ := r.InstantiateModule(ctx, compiled, wazero.NewModuleConfig().WithName("env.2")) -// defer env2.Close(ctx) // // Notes: // * ModuleBuilder is mutable. WithXXX functions return the same instance for chaining. @@ -157,10 +158,13 @@ type ModuleBuilder interface { ExportGlobalF64(name string, v float64) ModuleBuilder // Compile returns a module to instantiate, or an error if any of the configuration is invalid. + // + // Note: Closing the wazero.Runtime closes any CompiledModule it compiled. Compile(context.Context, CompileConfig) (CompiledModule, error) // Instantiate is a convenience that calls Build, then Runtime.InstantiateModule, using default configuration. // + // Note: Closing the wazero.Runtime closes any api.Module it instantiated. // Note: Fields in the builder are copied during instantiation: Later changes do not affect the instantiated result. // Note: To avoid using configuration defaults, use Compile instead. Instantiate(context.Context) (api.Module, error) diff --git a/config.go b/config.go index 4e6a706b..467f3ca0 100644 --- a/config.go +++ b/config.go @@ -218,6 +218,7 @@ func (c *runtimeConfig) WithWasmCore2() RuntimeConfig { // CompiledModule is a WebAssembly 1.0 module ready to be instantiated (Runtime.InstantiateModule) as an api.Module. // +// Note: Closing the wazero.Runtime closes any CompiledModule it compiled. // Note: In WebAssembly language, this is a decoded, validated, and possibly also compiled module. wazero avoids using // the name "Module" for both before and after instantiation as the name conflation has caused confusion. // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#semantic-phases%E2%91%A0 diff --git a/example_test.go b/example_test.go index 4c35949b..cbc6be82 100644 --- a/example_test.go +++ b/example_test.go @@ -27,7 +27,7 @@ func Example() { (export "add" (func $add)) )`)) if err != nil { - log.Fatal(err) + log.Panicln(err) } defer mod.Close(ctx) @@ -37,7 +37,7 @@ func Example() { x, y := uint64(1), uint64(2) results, err := add.Call(ctx, x, y) if err != nil { - log.Fatal(err) + log.Panicln(err) } fmt.Printf("%s: %d + %d = %d\n", mod.Name(), x, y, results[0]) diff --git a/examples/allocation/rust/greet.go b/examples/allocation/rust/greet.go index 0e396734..6fbedc78 100644 --- a/examples/allocation/rust/greet.go +++ b/examples/allocation/rust/greet.go @@ -25,24 +25,23 @@ func main() { // Create a new WebAssembly Runtime. r := wazero.NewRuntime() + defer r.Close(ctx) // This closes everything this Runtime created. // Instantiate a Go-defined module named "env" that exports a function to // log to the console. - env, err := r.NewModuleBuilder("env"). + _, err := r.NewModuleBuilder("env"). ExportFunction("log", logString). Instantiate(ctx) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer env.Close(ctx) // Instantiate a WebAssembly module that imports the "log" function defined // in "env" and exports "memory" and functions we'll use in this example. mod, err := r.InstantiateModuleFromCode(ctx, greetWasm) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer mod.Close(ctx) // Get references to WebAssembly functions we'll use in this example. greet := mod.ExportedFunction("greet") @@ -59,7 +58,7 @@ func main() { // function could be used to pass binary serialized data to Wasm. results, err := allocate.Call(ctx, nameSize) if err != nil { - log.Fatal(err) + log.Panicln(err) } namePtr := results[0] // This pointer was allocated by Rust, but owned by Go, So, we have to @@ -68,21 +67,21 @@ func main() { // The pointer is a linear memory offset, which is where we write the name. if !mod.Memory().Write(ctx, uint32(namePtr), []byte(name)) { - log.Fatalf("Memory.Write(%d, %d) out of range of memory size %d", + log.Panicf("Memory.Write(%d, %d) out of range of memory size %d", namePtr, nameSize, mod.Memory().Size(ctx)) } // Now, we can call "greet", which reads the string we wrote to memory! _, err = greet.Call(ctx, namePtr, nameSize) if err != nil { - log.Fatal(err) + log.Panicln(err) } // Finally, we get the greeting message "greet" printed. This shows how to // read-back something allocated by Rust. ptrSize, err := greeting.Call(ctx, namePtr, nameSize) if err != nil { - log.Fatal(err) + log.Panicln(err) } greetingPtr := uint32(ptrSize[0] >> 32) greetingSize := uint32(ptrSize[0]) @@ -92,7 +91,7 @@ func main() { // The pointer is a linear memory offset, which is where we write the name. if bytes, ok := mod.Memory().Read(ctx, greetingPtr, greetingSize); !ok { - log.Fatalf("Memory.Read(%d, %d) out of range of memory size %d", + log.Panicf("Memory.Read(%d, %d) out of range of memory size %d", greetingPtr, greetingSize, mod.Memory().Size(ctx)) } else { fmt.Println("go >>", string(bytes)) @@ -102,7 +101,7 @@ func main() { func logString(ctx context.Context, m api.Module, offset, byteCount uint32) { buf, ok := m.Memory().Read(ctx, offset, byteCount) if !ok { - log.Fatalf("Memory.Read(%d, %d) out of range", offset, byteCount) + log.Panicf("Memory.Read(%d, %d) out of range", offset, byteCount) } fmt.Println(string(buf)) } diff --git a/examples/allocation/tinygo/greet.go b/examples/allocation/tinygo/greet.go index 59d70129..2b5e3fe0 100644 --- a/examples/allocation/tinygo/greet.go +++ b/examples/allocation/tinygo/greet.go @@ -26,32 +26,29 @@ func main() { // Create a new WebAssembly Runtime. r := wazero.NewRuntime() + defer r.Close(ctx) // This closes everything this Runtime created. // Instantiate a Go-defined module named "env" that exports a function to // log to the console. - env, err := r.NewModuleBuilder("env"). + _, err := r.NewModuleBuilder("env"). ExportFunction("log", logString). Instantiate(ctx) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer env.Close(ctx) // Note: testdata/greet.go doesn't use WASI, but TinyGo needs it to // implement functions such as panic. - wm, err := wasi.InstantiateSnapshotPreview1(ctx, r) - if err != nil { - log.Fatal(err) + if _, err = wasi.InstantiateSnapshotPreview1(ctx, r); err != nil { + log.Panicln(err) } - defer wm.Close(ctx) // Instantiate a WebAssembly module that imports the "log" function defined // in "env" and exports "memory" and functions we'll use in this example. mod, err := r.InstantiateModuleFromCode(ctx, greetWasm) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer mod.Close(ctx) // Get references to WebAssembly functions we'll use in this example. greet := mod.ExportedFunction("greet") @@ -69,7 +66,7 @@ func main() { // function could be used to pass binary serialized data to Wasm. results, err := malloc.Call(ctx, nameSize) if err != nil { - log.Fatal(err) + log.Panicln(err) } namePtr := results[0] // This pointer is managed by TinyGo, but TinyGo is unaware of external usage. @@ -78,28 +75,28 @@ func main() { // The pointer is a linear memory offset, which is where we write the name. if !mod.Memory().Write(ctx, uint32(namePtr), []byte(name)) { - log.Fatalf("Memory.Write(%d, %d) out of range of memory size %d", + log.Panicf("Memory.Write(%d, %d) out of range of memory size %d", namePtr, nameSize, mod.Memory().Size(ctx)) } // Now, we can call "greet", which reads the string we wrote to memory! _, err = greet.Call(ctx, namePtr, nameSize) if err != nil { - log.Fatal(err) + log.Panicln(err) } // Finally, we get the greeting message "greet" printed. This shows how to // read-back something allocated by TinyGo. ptrSize, err := greeting.Call(ctx, namePtr, nameSize) if err != nil { - log.Fatal(err) + log.Panicln(err) } // Note: This pointer is still owned by TinyGo, so don't try to free it! greetingPtr := uint32(ptrSize[0] >> 32) greetingSize := uint32(ptrSize[0]) // The pointer is a linear memory offset, which is where we write the name. if bytes, ok := mod.Memory().Read(ctx, greetingPtr, greetingSize); !ok { - log.Fatalf("Memory.Read(%d, %d) out of range of memory size %d", + log.Panicf("Memory.Read(%d, %d) out of range of memory size %d", greetingPtr, greetingSize, mod.Memory().Size(ctx)) } else { fmt.Println("go >>", string(bytes)) @@ -109,7 +106,7 @@ func main() { func logString(ctx context.Context, m api.Module, offset, byteCount uint32) { buf, ok := m.Memory().Read(ctx, offset, byteCount) if !ok { - log.Fatalf("Memory.Read(%d, %d) out of range", offset, byteCount) + log.Panicf("Memory.Read(%d, %d) out of range", offset, byteCount) } fmt.Println(string(buf)) } diff --git a/examples/basic/add.go b/examples/basic/add.go index fa476ae8..dc47d18f 100644 --- a/examples/basic/add.go +++ b/examples/basic/add.go @@ -19,6 +19,7 @@ func main() { // Create a new WebAssembly Runtime. r := wazero.NewRuntime() + defer r.Close(ctx) // This closes everything this Runtime created. // Add a module to the runtime named "wasm/math" which exports one function "add", implemented in WebAssembly. wasm, err := r.InstantiateModuleFromCode(ctx, []byte(`(module $wasm/math @@ -30,9 +31,8 @@ func main() { (export "add" (func $add)) )`)) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer wasm.Close(ctx) // Add a module to the runtime named "host/math" which exports one function "add", implemented in Go. host, err := r.NewModuleBuilder("host/math"). @@ -40,9 +40,8 @@ func main() { return v1 + v2 }).Instantiate(ctx) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer host.Close(ctx) // Read two args to add. x, y := readTwoArgs() @@ -52,7 +51,7 @@ func main() { add := mod.ExportedFunction("add") results, err := add.Call(ctx, x, y) if err != nil { - log.Fatal(err) + log.Panicln(err) } fmt.Printf("%s: %d + %d = %d\n", mod.Name(), x, y, results[0]) @@ -62,12 +61,12 @@ func main() { func readTwoArgs() (uint64, uint64) { x, err := strconv.ParseUint(os.Args[1], 10, 64) if err != nil { - log.Fatalf("invalid arg %v: %v", os.Args[1], err) + log.Panicf("invalid arg %v: %v", os.Args[1], err) } y, err := strconv.ParseUint(os.Args[2], 10, 64) if err != nil { - log.Fatalf("invalid arg %v: %v", os.Args[2], err) + log.Panicf("invalid arg %v: %v", os.Args[2], err) } return x, y } diff --git a/examples/import-go/age-calculator.go b/examples/import-go/age-calculator.go index 838411b7..b01c2467 100644 --- a/examples/import-go/age-calculator.go +++ b/examples/import-go/age-calculator.go @@ -22,6 +22,7 @@ func main() { // Create a new WebAssembly Runtime. r := wazero.NewRuntime() + defer r.Close(ctx) // This closes everything this Runtime created. // Instantiate a Go-defined module named "env" that exports functions to // get the current year and log to the console. @@ -30,7 +31,7 @@ func main() { // constrained to a subset of numeric types. // Note: "env" is a module name conventionally used for arbitrary // host-defined functions, but any name would do. - env, err := r.NewModuleBuilder("env"). + _, err := r.NewModuleBuilder("env"). ExportFunction("log_i32", func(v uint32) { fmt.Println("log_i32 >>", v) }). @@ -42,9 +43,8 @@ func main() { }). Instantiate(ctx) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer env.Close(ctx) // Instantiate a WebAssembly module named "age-calculator" that imports // functions defined in "env". @@ -85,26 +85,25 @@ func main() { )`)) // ^^ Note: wazero's text compiler is incomplete #59. We are using it anyway to keep this example dependency free. if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer ageCalculator.Close(ctx) // Read the birthYear from the arguments to main birthYear, err := strconv.ParseUint(os.Args[1], 10, 64) if err != nil { - log.Fatalf("invalid arg %v: %v", os.Args[1], err) + log.Panicf("invalid arg %v: %v", os.Args[1], err) } // First, try calling the "get_age" function and printing to the console externally. results, err := ageCalculator.ExportedFunction("get_age").Call(ctx, birthYear) if err != nil { - log.Fatal(err) + log.Panicln(err) } fmt.Println("println >>", results[0]) // First, try calling the "log_age" function and printing to the console externally. _, err = ageCalculator.ExportedFunction("log_age").Call(ctx, birthYear) if err != nil { - log.Fatal(err) + log.Panicln(err) } } diff --git a/examples/multiple-results/multiple-results.go b/examples/multiple-results/multiple-results.go index c9d583cd..5c28301d 100644 --- a/examples/multiple-results/multiple-results.go +++ b/examples/multiple-results/multiple-results.go @@ -29,21 +29,20 @@ func main() { ctx := context.Background() // Create a new WebAssembly Runtime. - runtime := wazero.NewRuntime() + r := wazero.NewRuntime() + defer r.Close(ctx) // This closes everything this Runtime created. // Add a module that uses offset parameters for multiple results, with functions defined in WebAssembly. - wasm, err := resultOffsetWasmFunctions(ctx, runtime) + wasm, err := resultOffsetWasmFunctions(ctx, r) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer wasm.Close(ctx) // Add a module that uses offset parameters for multiple results, with functions defined in Go. - host, err := resultOffsetHostFunctions(ctx, runtime) + host, err := resultOffsetHostFunctions(ctx, r) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer host.Close(ctx) // wazero enables only W3C recommended features by default. Opt-in to other features like so: runtimeWithMultiValue := wazero.NewRuntimeWithConfig( @@ -54,23 +53,21 @@ func main() { // Add a module that uses multiple results values, with functions defined in WebAssembly. wasmWithMultiValue, err := multiValueWasmFunctions(ctx, runtimeWithMultiValue) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer wasmWithMultiValue.Close(ctx) // Add a module that uses multiple results values, with functions defined in Go. hostWithMultiValue, err := multiValueHostFunctions(ctx, runtimeWithMultiValue) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer hostWithMultiValue.Close(ctx) // Call the same function in all modules and print the results to the console. for _, mod := range []api.Module{wasm, host, wasmWithMultiValue, hostWithMultiValue} { getAge := mod.ExportedFunction("call_get_age") results, err := getAge.Call(ctx) if err != nil { - log.Fatal(err) + log.Panicln(err) } fmt.Printf("%s: age=%d\n", mod.Name(), results[0]) diff --git a/examples/replace-import/replace-import.go b/examples/replace-import/replace-import.go index 99e89a13..0fc1c9e2 100644 --- a/examples/replace-import/replace-import.go +++ b/examples/replace-import/replace-import.go @@ -18,6 +18,7 @@ func main() { // Create a new WebAssembly Runtime. r := wazero.NewRuntime() + defer r.Close(ctx) // This closes everything this Runtime created. // Instantiate a Go-defined module named "assemblyscript" that exports a // function to close the module that calls "abort". @@ -26,7 +27,7 @@ func main() { _ = m.CloseWithExitCode(ctx, 255) }).Instantiate(ctx) if err != nil { - log.Fatal(err) + log.Panicln(err) } defer host.Close(ctx) @@ -45,14 +46,14 @@ func main() { (export "abort" (func 0)) ;; exports the import for testing )`), compileConfig) if err != nil { - log.Fatal(err) + log.Panicln(err) } defer code.Close(ctx) // Instantiate the WebAssembly module. mod, err := r.InstantiateModule(ctx, code, wazero.NewModuleConfig()) if err != nil { - log.Fatal(err) + log.Panicln(err) } defer mod.Close(ctx) diff --git a/examples/wasi/cat.go b/examples/wasi/cat.go index 76f2e82c..f186c669 100644 --- a/examples/wasi/cat.go +++ b/examples/wasi/cat.go @@ -30,36 +30,32 @@ func main() { // Create a new WebAssembly Runtime. r := wazero.NewRuntime() + defer r.Close(ctx) // This closes everything this Runtime created. // Since wazero uses fs.FS, we can use standard libraries to do things like trim the leading path. rooted, err := fs.Sub(catFS, "testdata") if err != nil { - log.Fatal(err) + log.Panicln(err) } // Combine the above into our baseline config, overriding defaults (which discard stdout and have no file system). config := wazero.NewModuleConfig().WithStdout(os.Stdout).WithFS(rooted) // Instantiate WASI, which implements system I/O such as console output. - wm, err := wasi.InstantiateSnapshotPreview1(ctx, r) - if err != nil { - log.Fatal(err) + if _, err = wasi.InstantiateSnapshotPreview1(ctx, r); err != nil { + log.Panicln(err) } - defer wm.Close(ctx) // Compile the WebAssembly module using the default configuration. code, err := r.CompileModule(ctx, catWasm, wazero.NewCompileConfig()) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer code.Close(ctx) // InstantiateModule runs the "_start" function which is what TinyGo compiles "main" to. // * Set the program name (arg[0]) to "wasi" and add args to write "test.txt" to stdout twice. // * We use "/test.txt" or "./test.txt" because WithFS by default maps the workdir "." to "/". - cat, err := r.InstantiateModule(ctx, code, config.WithArgs("wasi", os.Args[1])) - if err != nil { - log.Fatal(err) + if _, err = r.InstantiateModule(ctx, code, config.WithArgs("wasi", os.Args[1])); err != nil { + log.Panicln(err) } - defer cat.Close(ctx) } diff --git a/experimental/listener_test.go b/experimental/listener_test.go index e4ae4523..75107870 100644 --- a/experimental/listener_test.go +++ b/experimental/listener_test.go @@ -60,11 +60,11 @@ func Example_listener() { ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, &loggerFactory{}) r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfigInterpreter()) - wm, err := wasi.InstantiateSnapshotPreview1(ctx, r) - if err != nil { - log.Fatal(err) + defer r.Close(ctx) // This closes everything this Runtime created. + + if _, err := wasi.InstantiateSnapshotPreview1(ctx, r); err != nil { + log.Panicln(err) } - defer wm.Close(ctx) // Compile the WebAssembly module using the default configuration. code, err := r.CompileModule(ctx, []byte(`(module $listener @@ -75,15 +75,13 @@ func Example_listener() { (start 1) ;; call the second function )`), wazero.NewCompileConfig()) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer code.Close(ctx) - mod, err := r.InstantiateModule(ctx, code, wazero.NewModuleConfig().WithStdout(os.Stdout)) + _, err = r.InstantiateModule(ctx, code, wazero.NewModuleConfig().WithStdout(os.Stdout)) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer mod.Close(ctx) // Output: // >> listener.[1] diff --git a/experimental/sys_test.go b/experimental/sys_test.go index 3477caa0..96419803 100644 --- a/experimental/sys_test.go +++ b/experimental/sys_test.go @@ -37,11 +37,11 @@ func Example_sys() { ctx := context.WithValue(context.Background(), experimental.SysKey{}, &fakeSys{}) r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfigInterpreter()) - wm, err := wasi.InstantiateSnapshotPreview1(ctx, r) - if err != nil { - log.Fatal(err) + defer r.Close(ctx) // This closes everything this Runtime created. + + if _, err := wasi.InstantiateSnapshotPreview1(ctx, r); err != nil { + log.Panicln(err) } - defer wm.Close(ctx) code, err := r.CompileModule(ctx, []byte(`(module (import "wasi_snapshot_preview1" "random_get" @@ -51,19 +51,17 @@ func Example_sys() { (start 1) ;; call the second function )`), wazero.NewCompileConfig()) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer code.Close(ctx) mod, err := r.InstantiateModule(ctx, code, wazero.NewModuleConfig().WithStdout(os.Stdout)) if err != nil { - log.Fatal(err) + log.Panicln(err) } - defer mod.Close(ctx) // Try to read 4 bytes of random data. if bytes, ok := mod.Memory().Read(ctx, 0, 4); !ok { - log.Fatalf("Memory.Read(0, 4) out of range of memory size %d", mod.Memory().Size(ctx)) + log.Panicf("Memory.Read(0, 4) out of range of memory size %d", mod.Memory().Size(ctx)) } else { fmt.Println(hex.EncodeToString(bytes)) } diff --git a/wasi/example_test.go b/wasi/example_test.go index 3d92dcd4..4aa8421a 100644 --- a/wasi/example_test.go +++ b/wasi/example_test.go @@ -23,7 +23,7 @@ func Example() { // Instantiate WASI, which implements system I/O such as console output. wm, err := InstantiateSnapshotPreview1(ctx, r) if err != nil { - log.Fatal(err) + log.Panicln(err) } defer wm.Close(testCtx) @@ -40,7 +40,7 @@ func Example() { ) `), wazero.NewCompileConfig()) if err != nil { - log.Fatal(err) + log.Panicln(err) } defer code.Close(ctx) diff --git a/wasi/wasi.go b/wasi/wasi.go index 852c1214..fd9e5d04 100644 --- a/wasi/wasi.go +++ b/wasi/wasi.go @@ -26,7 +26,17 @@ const ModuleSnapshotPreview1 = "wasi_snapshot_preview1" // InstantiateSnapshotPreview1 instantiates ModuleSnapshotPreview1, so that other modules can import them. // +// Ex. If your source (%.wasm binary) includes an import "wasi_snapshot_preview1", call InstantiateSnapshotPreview1 +// prior to instantiating it. Otherwise, it will error due to missing imports. +// ctx := context.Background() +// r := wazero.NewRuntime() +// defer r.Close(ctx) // This closes everything this Runtime created. +// +// _, _ = wasi.InstantiateSnapshotPreview1(ctx, r) +// mod, _ := r.InstantiateModuleFromCode(ctx, source) +// // Note: All WASI functions return a single Errno result, ErrnoSuccess on success. +// Note: Closing the wazero.Runtime closes any api.Module it instantiated. func InstantiateSnapshotPreview1(ctx context.Context, r wazero.Runtime) (api.Module, error) { _, fns := snapshotPreview1Functions(ctx) return r.NewModuleBuilder(ModuleSnapshotPreview1).ExportFunctions(fns).Instantiate(ctx) diff --git a/wasm.go b/wasm.go index 905b6574..ce73069c 100644 --- a/wasm.go +++ b/wasm.go @@ -16,11 +16,12 @@ import ( // Runtime allows embedding of WebAssembly modules. // -// Ex. +// Ex. The below is the basic initialization of wazero's WebAssembly Runtime. // ctx := context.Background() // r := wazero.NewRuntime() +// defer r.Close(ctx) // This closes everything this Runtime created. +// // module, _ := r.InstantiateModuleFromCode(ctx, source) -// defer module.Close() type Runtime interface { // NewModuleBuilder lets you create modules out of functions defined in Go. // @@ -52,8 +53,10 @@ type Runtime interface { // // Ex. // ctx := context.Background() - // module, _ := wazero.NewRuntime().InstantiateModuleFromCode(ctx, source) - // defer module.Close() + // r := wazero.NewRuntime() + // defer r.Close(ctx) // This closes everything this Runtime created. + // + // module, _ := r.InstantiateModuleFromCode(ctx, source) // // Note: When the context is nil, it defaults to context.Background. // Note: This is a convenience utility that chains CompileModule with InstantiateModule. To instantiate the same @@ -66,10 +69,10 @@ type Runtime interface { // Ex. // ctx := context.Background() // r := wazero.NewRuntime() + // defer r.Close(ctx) // This closes everything this Runtime created. + // // compiled, _ := r.CompileModule(ctx, source, wazero.NewCompileConfig()) - // defer compiled.Close() // module, _ := r.InstantiateModule(ctx, compiled, wazero.NewModuleConfig().WithName("prod")) - // defer module.Close() // // While CompiledModule is pre-validated, there are a few situations which can cause an error: // * The module name is already in use. @@ -80,7 +83,9 @@ type Runtime interface { // // ctx := context.Background() // r := wazero.NewRuntime() - // wasi, _ := wasi.InstantiateSnapshotPreview1(r) + // defer r.Close(ctx) // This closes everything this Runtime created. + // + // _, _ := wasi.InstantiateSnapshotPreview1(r) // compiled, _ := r.CompileModule(ctx, source, wazero.NewCompileConfig()) // // // Initialize base configuration: @@ -99,7 +104,9 @@ type Runtime interface { // Ex. // ctx := context.Background() // r := wazero.NewRuntime() - // defer r.Close(ctx) + // defer r.Close(ctx) // This closes everything this Runtime created. + // + // // Everything below here can be closed, but will anyway due to above. // _, _ = wasi.InstantiateSnapshotPreview1(ctx, r) // mod, _ := r.InstantiateModuleFromCode(ctx, source) Close(context.Context) error @@ -110,7 +117,9 @@ type Runtime interface { // Ex. // ctx := context.Background() // r := wazero.NewRuntime() - // defer r.CloseWithExitCode(ctx, 2) + // defer r.CloseWithExitCode(ctx, 2) // This closes everything this Runtime created. + // + // // Everything below here can be closed, but will anyway due to above. // _, _ = wasi.InstantiateSnapshotPreview1(ctx, r) // mod, _ := r.InstantiateModuleFromCode(ctx, source) CloseWithExitCode(ctx context.Context, exitCode uint32) error