wa-lang.org/wazero@v1.0.2/imports/go/example/stars.go (about) 1 package main 2 3 import ( 4 "context" 5 "io" 6 "log" 7 "net/http" 8 "os" 9 "path" 10 "path/filepath" 11 "strings" 12 "time" 13 14 "wa-lang.org/wazero" 15 "wa-lang.org/wazero/experimental" 16 gojs "wa-lang.org/wazero/imports/go" 17 "wa-lang.org/wazero/sys" 18 ) 19 20 // main invokes Wasm compiled via `GOARCH=wasm GOOS=js`, which reports the star 21 // count of wazero. 22 // 23 // This shows how to integrate an HTTP client with wasm using gojs. 24 func main() { 25 // The Wasm binary (stars/main.wasm) is very large (>7.5MB). Use wazero's 26 // compilation cache to reduce performance penalty of multiple runs. 27 compilationCacheDir := ".build" 28 ctx, err := experimental.WithCompilationCacheDirName(context.Background(), compilationCacheDir) 29 if err != nil { 30 log.Panicln(err) 31 } 32 33 // Create a new WebAssembly Runtime. 34 r := wazero.NewRuntime(ctx) 35 defer r.Close(ctx) // This closes everything this Runtime created. 36 37 // Combine the above into our baseline config, overriding defaults. 38 config := wazero.NewModuleConfig(). 39 // By default, I/O streams are discarded, so you won't see output. 40 WithStdout(os.Stdout).WithStderr(os.Stderr) 41 42 bin, err := os.ReadFile(path.Join("stars", "main.wasm")) 43 if err != nil { 44 log.Panicln(err) 45 } 46 47 // Compile the WebAssembly module using the default configuration. 48 start := time.Now() 49 compiled, err := r.CompileModule(ctx, bin) 50 if err != nil { 51 log.Panicln(err) 52 } 53 compilationTime := time.Since(start).Milliseconds() 54 log.Printf("CompileModule took %dms with %dKB cache", compilationTime, dirSize(compilationCacheDir)/1024) 55 56 // Instead of making real HTTP calls, return fake data. 57 ctx = gojs.WithRoundTripper(ctx, &fakeGitHub{}) 58 59 // Execute the "run" function, which corresponds to "main" in stars/main.go. 60 start = time.Now() 61 err = gojs.Run(ctx, r, compiled, config) 62 runTime := time.Since(start).Milliseconds() 63 log.Printf("gojs.Run took %dms", runTime) 64 if exitErr, ok := err.(*sys.ExitError); ok && exitErr.ExitCode() != 0 { 65 log.Panicln(err) 66 } else if !ok { 67 log.Panicln(err) 68 } 69 } 70 71 // compile-time check to ensure fakeGitHub implements http.RoundTripper 72 var _ http.RoundTripper = &fakeGitHub{} 73 74 type fakeGitHub struct{} 75 76 func (f *fakeGitHub) RoundTrip(*http.Request) (*http.Response, error) { 77 fakeResponse := `{"stargazers_count": 9999999}` 78 return &http.Response{ 79 StatusCode: http.StatusOK, 80 Status: http.StatusText(http.StatusOK), 81 Body: io.NopCloser(strings.NewReader(fakeResponse)), 82 ContentLength: int64(len(fakeResponse)), 83 }, nil 84 } 85 86 func dirSize(dir string) int64 { 87 var size int64 88 _ = filepath.Walk(dir, func(_ string, info os.FileInfo, err error) error { 89 if err != nil { 90 log.Panicln(err) 91 } 92 if !info.IsDir() { 93 size += info.Size() 94 } 95 return nil 96 }) 97 return size 98 }