github.com/tetratelabs/wazero@v1.2.1/imports/emscripten/emscripten.go (about) 1 // Package emscripten contains Go-defined special functions imported by 2 // Emscripten under the module name "env". 3 // 4 // Emscripten has many imports which are triggered on build flags. Use 5 // FunctionExporter, instead of Instantiate, to define more "env" functions. 6 // 7 // # Relationship to WASI 8 // 9 // Emscripten typically requires wasi_snapshot_preview1 to implement exit. 10 // 11 // See wasi_snapshot_preview1.Instantiate and 12 // https://github.com/emscripten-core/emscripten/wiki/WebAssembly-Standalone 13 package emscripten 14 15 import ( 16 "context" 17 "strings" 18 19 "github.com/tetratelabs/wazero" 20 "github.com/tetratelabs/wazero/api" 21 internal "github.com/tetratelabs/wazero/internal/emscripten" 22 "github.com/tetratelabs/wazero/internal/wasm" 23 ) 24 25 const i32 = wasm.ValueTypeI32 26 27 // MustInstantiate calls Instantiate or panics on error. 28 // 29 // This is a simpler function for those who know the module "env" is not 30 // already instantiated, and don't need to unload it. 31 func MustInstantiate(ctx context.Context, r wazero.Runtime) { 32 if _, err := Instantiate(ctx, r); err != nil { 33 panic(err) 34 } 35 } 36 37 // Instantiate instantiates the "env" module used by Emscripten into the 38 // runtime. 39 // 40 // # Notes 41 // 42 // - Failure cases are documented on wazero.Runtime InstantiateModule. 43 // - Closing the wazero.Runtime has the same effect as closing the result. 44 // - To add more functions to the "env" module, use FunctionExporter. 45 func Instantiate(ctx context.Context, r wazero.Runtime) (api.Closer, error) { 46 builder := r.NewHostModuleBuilder("env") 47 NewFunctionExporter().ExportFunctions(builder) 48 return builder.Instantiate(ctx) 49 } 50 51 // FunctionExporter configures the functions in the "env" module used by 52 // Emscripten. 53 // 54 // # Notes 55 // 56 // - This is an interface for decoupling, not third-party implementations. 57 // All implementations are in wazero. 58 type FunctionExporter interface { 59 // ExportFunctions builds functions to export with a wazero.HostModuleBuilder 60 // named "env". 61 ExportFunctions(wazero.HostModuleBuilder) 62 } 63 64 // NewFunctionExporter returns a FunctionExporter object with trace disabled. 65 func NewFunctionExporter() FunctionExporter { 66 return &functionExporter{} 67 } 68 69 type functionExporter struct{} 70 71 // ExportFunctions implements FunctionExporter.ExportFunctions 72 func (functionExporter) ExportFunctions(builder wazero.HostModuleBuilder) { 73 exporter := builder.(wasm.HostFuncExporter) 74 exporter.ExportHostFunc(internal.NotifyMemoryGrowth) 75 } 76 77 type emscriptenFns []*wasm.HostFunc 78 79 // InstantiateForModule instantiates a module named "env" populated with any 80 // known functions used in emscripten. 81 func InstantiateForModule(ctx context.Context, r wazero.Runtime, guest wazero.CompiledModule) (api.Closer, error) { 82 // Create the exporter for the supplied wasm 83 exporter, err := NewFunctionExporterForModule(guest) 84 if err != nil { 85 return nil, err 86 } 87 88 // Instantiate it! 89 env := r.NewHostModuleBuilder("env") 90 exporter.ExportFunctions(env) 91 return env.Instantiate(ctx) 92 } 93 94 // NewFunctionExporterForModule returns a guest-specific FunctionExporter, 95 // populated with any known functions used in emscripten. 96 func NewFunctionExporterForModule(guest wazero.CompiledModule) (FunctionExporter, error) { 97 ret := emscriptenFns{} 98 for _, fn := range guest.ImportedFunctions() { 99 importModule, importName, isImport := fn.Import() 100 if !isImport || importModule != "env" { 101 continue // not emscripten 102 } 103 if importName == internal.FunctionNotifyMemoryGrowth { 104 ret = append(ret, internal.NotifyMemoryGrowth) 105 continue 106 } 107 if !strings.HasPrefix(importName, internal.InvokePrefix) { 108 continue // not invoke, and maybe not emscripten 109 } 110 111 hf := internal.NewInvokeFunc(importName, fn.ParamTypes(), fn.ResultTypes()) 112 ret = append(ret, hf) 113 } 114 return ret, nil 115 } 116 117 // ExportFunctions implements FunctionExporter.ExportFunctions 118 func (i emscriptenFns) ExportFunctions(builder wazero.HostModuleBuilder) { 119 exporter := builder.(wasm.HostFuncExporter) 120 for _, fn := range i { 121 exporter.ExportHostFunc(fn) 122 } 123 }