Makes ExportedFunctions unique (#698)
Exported functions are easier to use as a map vs making the callers do it. Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
27
config.go
27
config.go
@@ -267,15 +267,24 @@ func (c *runtimeConfig) WithWasmCore2() RuntimeConfig {
|
||||
//
|
||||
// Note: Closing the wazero.Runtime closes any CompiledModule it compiled.
|
||||
type CompiledModule interface {
|
||||
// ImportedFunctions returns all the imported functions (api.FunctionDefinition) in this module.
|
||||
// Name returns the module name encoded into the binary or empty if not.
|
||||
Name() string
|
||||
|
||||
// ImportedFunctions returns all the imported functions
|
||||
// (api.FunctionDefinition) in this module or nil if there are none.
|
||||
//
|
||||
// Note: Unlike ExportedFunctions, there is no unique constraint on
|
||||
// imports.
|
||||
ImportedFunctions() []api.FunctionDefinition
|
||||
|
||||
// ExportedFunctions returns all the exported functions (api.FunctionDefinition) in this module.
|
||||
ExportedFunctions() []api.FunctionDefinition
|
||||
// ExportedFunctions returns all the exported functions
|
||||
// (api.FunctionDefinition) in this module keyed on export name.
|
||||
ExportedFunctions() map[string]api.FunctionDefinition
|
||||
|
||||
// Close releases all the allocated resources for this CompiledModule.
|
||||
//
|
||||
// Note: It is safe to call Close while having outstanding calls from an api.Module instantiated from this.
|
||||
// Note: It is safe to call Close while having outstanding calls from an
|
||||
// api.Module instantiated from this.
|
||||
Close(context.Context) error
|
||||
}
|
||||
|
||||
@@ -289,6 +298,14 @@ type compiledModule struct {
|
||||
closeWithModule bool
|
||||
}
|
||||
|
||||
// Name implements CompiledModule.Name
|
||||
func (c *compiledModule) Name() (moduleName string) {
|
||||
if ns := c.module.NameSection; ns != nil {
|
||||
moduleName = ns.ModuleName
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Close implements CompiledModule.Close
|
||||
func (c *compiledModule) Close(_ context.Context) error {
|
||||
// Note: If you use the context.Context param, don't forget to coerce nil to context.Background()!
|
||||
@@ -304,7 +321,7 @@ func (c *compiledModule) ImportedFunctions() []api.FunctionDefinition {
|
||||
}
|
||||
|
||||
// ExportedFunctions implements CompiledModule.ExportedFunctions
|
||||
func (c *compiledModule) ExportedFunctions() []api.FunctionDefinition {
|
||||
func (c *compiledModule) ExportedFunctions() map[string]api.FunctionDefinition {
|
||||
return c.module.ExportedFunctions()
|
||||
}
|
||||
|
||||
|
||||
@@ -689,6 +689,7 @@ func TestModuleConfig_toSysContext_Errors(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestModuleConfig_clone(t *testing.T) {
|
||||
mc := NewModuleConfig().(*moduleConfig)
|
||||
cloned := mc.clone()
|
||||
@@ -707,7 +708,37 @@ func TestModuleConfig_clone(t *testing.T) {
|
||||
require.Nil(t, cloned.fs)
|
||||
}
|
||||
|
||||
func TestCompiledCode_Close(t *testing.T) {
|
||||
func Test_compiledModule_Name(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input *compiledModule
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "no name section",
|
||||
input: &compiledModule{module: &wasm.Module{}},
|
||||
},
|
||||
{
|
||||
name: "empty name",
|
||||
input: &compiledModule{module: &wasm.Module{NameSection: &wasm.NameSection{}}},
|
||||
},
|
||||
{
|
||||
name: "name",
|
||||
input: &compiledModule{module: &wasm.Module{NameSection: &wasm.NameSection{ModuleName: "foo"}}},
|
||||
expected: "foo",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tc := tt
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require.Equal(t, tc.expected, tc.input.Name())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_compiledModule_Close(t *testing.T) {
|
||||
for _, ctx := range []context.Context{nil, testCtx} { // Ensure it doesn't crash on nil!
|
||||
e := &mockEngine{name: "1", cachedModules: map[*wasm.Module]struct{}{}}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
// NewLoggingListenerFactory implements FunctionListenerFactory to log all
|
||||
// function calls to the writer.
|
||||
// functions that have a name to the writer.
|
||||
func NewLoggingListenerFactory(writer io.Writer) FunctionListenerFactory {
|
||||
return &loggingListenerFactory{writer}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
)
|
||||
|
||||
// ImportedFunctions returns the definitions of each imported function.
|
||||
//
|
||||
// Note: Unlike ExportedFunctions, there is no unique constraint on imports.
|
||||
func (m *Module) ImportedFunctions() (ret []api.FunctionDefinition) {
|
||||
for _, d := range m.FunctionDefinitionSection {
|
||||
if d.importDesc != nil {
|
||||
@@ -16,13 +18,14 @@ func (m *Module) ImportedFunctions() (ret []api.FunctionDefinition) {
|
||||
}
|
||||
|
||||
// ExportedFunctions returns the definitions of each exported function.
|
||||
func (m *Module) ExportedFunctions() (ret []api.FunctionDefinition) {
|
||||
func (m *Module) ExportedFunctions() map[string]api.FunctionDefinition {
|
||||
ret := map[string]api.FunctionDefinition{}
|
||||
for _, d := range m.FunctionDefinitionSection {
|
||||
if d.exportNames != nil {
|
||||
ret = append(ret, d)
|
||||
for _, e := range d.exportNames {
|
||||
ret[e] = d
|
||||
}
|
||||
}
|
||||
return
|
||||
return ret
|
||||
}
|
||||
|
||||
// BuildFunctionDefinitions generates function metadata that can be parsed from
|
||||
|
||||
@@ -12,14 +12,16 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
|
||||
nopCode := &Code{nil, []byte{OpcodeEnd}}
|
||||
fnV := reflect.ValueOf(func() {})
|
||||
tests := []struct {
|
||||
name string
|
||||
m *Module
|
||||
expected []*FunctionDefinition
|
||||
expectedImports, expectedExports []api.FunctionDefinition
|
||||
name string
|
||||
m *Module
|
||||
expected []*FunctionDefinition
|
||||
expectedImports []api.FunctionDefinition
|
||||
expectedExports map[string]api.FunctionDefinition
|
||||
}{
|
||||
{
|
||||
name: "no exports",
|
||||
m: &Module{},
|
||||
name: "no exports",
|
||||
m: &Module{},
|
||||
expectedExports: map[string]api.FunctionDefinition{},
|
||||
},
|
||||
{
|
||||
name: "no functions",
|
||||
@@ -27,6 +29,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
|
||||
ExportSection: []*Export{{Type: ExternTypeGlobal, Index: 0}},
|
||||
GlobalSection: []*Global{{}},
|
||||
},
|
||||
expectedExports: map[string]api.FunctionDefinition{},
|
||||
},
|
||||
{
|
||||
name: "host func",
|
||||
@@ -43,6 +46,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
|
||||
funcType: v_v,
|
||||
},
|
||||
},
|
||||
expectedExports: map[string]api.FunctionDefinition{},
|
||||
},
|
||||
{
|
||||
name: "without imports",
|
||||
@@ -81,20 +85,20 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
|
||||
funcType: v_v,
|
||||
},
|
||||
},
|
||||
expectedExports: []api.FunctionDefinition{
|
||||
&FunctionDefinition{
|
||||
expectedExports: map[string]api.FunctionDefinition{
|
||||
"function_index=0": &FunctionDefinition{
|
||||
index: 0,
|
||||
debugName: ".$0",
|
||||
exportNames: []string{"function_index=0"},
|
||||
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeI32}, Results: []ValueType{ValueTypeV128, ValueTypeI64}},
|
||||
},
|
||||
&FunctionDefinition{
|
||||
"function_index=1": &FunctionDefinition{
|
||||
index: 1,
|
||||
exportNames: []string{"function_index=1"},
|
||||
debugName: ".$1",
|
||||
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
|
||||
},
|
||||
&FunctionDefinition{
|
||||
"function_index=2": &FunctionDefinition{
|
||||
index: 2,
|
||||
debugName: ".$2",
|
||||
exportNames: []string{"function_index=2"},
|
||||
@@ -151,21 +155,21 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
|
||||
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
|
||||
},
|
||||
},
|
||||
expectedExports: []api.FunctionDefinition{
|
||||
&FunctionDefinition{
|
||||
expectedExports: map[string]api.FunctionDefinition{
|
||||
"imported_function": &FunctionDefinition{
|
||||
index: 0,
|
||||
debugName: ".$0",
|
||||
importDesc: &[2]string{"", ""},
|
||||
exportNames: []string{"imported_function"},
|
||||
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
|
||||
},
|
||||
&FunctionDefinition{
|
||||
"function_index=1": &FunctionDefinition{
|
||||
index: 1,
|
||||
debugName: ".$1",
|
||||
exportNames: []string{"function_index=1"},
|
||||
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeI32}, Results: []ValueType{ValueTypeV128, ValueTypeI64}},
|
||||
},
|
||||
&FunctionDefinition{
|
||||
"function_index=2": &FunctionDefinition{
|
||||
index: 2,
|
||||
debugName: ".$2",
|
||||
exportNames: []string{"function_index=2"},
|
||||
@@ -200,6 +204,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
|
||||
expectedImports: []api.FunctionDefinition{
|
||||
&FunctionDefinition{moduleName: "module", index: 0, debugName: "module.$0", importDesc: &[2]string{"i", "f"}, funcType: v_v},
|
||||
},
|
||||
expectedExports: map[string]api.FunctionDefinition{},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user