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.
|
// Note: Closing the wazero.Runtime closes any CompiledModule it compiled.
|
||||||
type CompiledModule interface {
|
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
|
ImportedFunctions() []api.FunctionDefinition
|
||||||
|
|
||||||
// ExportedFunctions returns all the exported functions (api.FunctionDefinition) in this module.
|
// ExportedFunctions returns all the exported functions
|
||||||
ExportedFunctions() []api.FunctionDefinition
|
// (api.FunctionDefinition) in this module keyed on export name.
|
||||||
|
ExportedFunctions() map[string]api.FunctionDefinition
|
||||||
|
|
||||||
// Close releases all the allocated resources for this CompiledModule.
|
// 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
|
Close(context.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,6 +298,14 @@ type compiledModule struct {
|
|||||||
closeWithModule bool
|
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
|
// Close implements CompiledModule.Close
|
||||||
func (c *compiledModule) Close(_ context.Context) error {
|
func (c *compiledModule) Close(_ context.Context) error {
|
||||||
// Note: If you use the context.Context param, don't forget to coerce nil to context.Background()!
|
// 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
|
// ExportedFunctions implements CompiledModule.ExportedFunctions
|
||||||
func (c *compiledModule) ExportedFunctions() []api.FunctionDefinition {
|
func (c *compiledModule) ExportedFunctions() map[string]api.FunctionDefinition {
|
||||||
return c.module.ExportedFunctions()
|
return c.module.ExportedFunctions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -689,6 +689,7 @@ func TestModuleConfig_toSysContext_Errors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestModuleConfig_clone(t *testing.T) {
|
func TestModuleConfig_clone(t *testing.T) {
|
||||||
mc := NewModuleConfig().(*moduleConfig)
|
mc := NewModuleConfig().(*moduleConfig)
|
||||||
cloned := mc.clone()
|
cloned := mc.clone()
|
||||||
@@ -707,7 +708,37 @@ func TestModuleConfig_clone(t *testing.T) {
|
|||||||
require.Nil(t, cloned.fs)
|
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!
|
for _, ctx := range []context.Context{nil, testCtx} { // Ensure it doesn't crash on nil!
|
||||||
e := &mockEngine{name: "1", cachedModules: map[*wasm.Module]struct{}{}}
|
e := &mockEngine{name: "1", cachedModules: map[*wasm.Module]struct{}{}}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewLoggingListenerFactory implements FunctionListenerFactory to log all
|
// 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 {
|
func NewLoggingListenerFactory(writer io.Writer) FunctionListenerFactory {
|
||||||
return &loggingListenerFactory{writer}
|
return &loggingListenerFactory{writer}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ImportedFunctions returns the definitions of each imported function.
|
// 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) {
|
func (m *Module) ImportedFunctions() (ret []api.FunctionDefinition) {
|
||||||
for _, d := range m.FunctionDefinitionSection {
|
for _, d := range m.FunctionDefinitionSection {
|
||||||
if d.importDesc != nil {
|
if d.importDesc != nil {
|
||||||
@@ -16,13 +18,14 @@ func (m *Module) ImportedFunctions() (ret []api.FunctionDefinition) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExportedFunctions returns the definitions of each exported function.
|
// 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 {
|
for _, d := range m.FunctionDefinitionSection {
|
||||||
if d.exportNames != nil {
|
for _, e := range d.exportNames {
|
||||||
ret = append(ret, d)
|
ret[e] = d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildFunctionDefinitions generates function metadata that can be parsed from
|
// BuildFunctionDefinitions generates function metadata that can be parsed from
|
||||||
|
|||||||
@@ -12,14 +12,16 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
|
|||||||
nopCode := &Code{nil, []byte{OpcodeEnd}}
|
nopCode := &Code{nil, []byte{OpcodeEnd}}
|
||||||
fnV := reflect.ValueOf(func() {})
|
fnV := reflect.ValueOf(func() {})
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
m *Module
|
m *Module
|
||||||
expected []*FunctionDefinition
|
expected []*FunctionDefinition
|
||||||
expectedImports, expectedExports []api.FunctionDefinition
|
expectedImports []api.FunctionDefinition
|
||||||
|
expectedExports map[string]api.FunctionDefinition
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no exports",
|
name: "no exports",
|
||||||
m: &Module{},
|
m: &Module{},
|
||||||
|
expectedExports: map[string]api.FunctionDefinition{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no functions",
|
name: "no functions",
|
||||||
@@ -27,6 +29,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
|
|||||||
ExportSection: []*Export{{Type: ExternTypeGlobal, Index: 0}},
|
ExportSection: []*Export{{Type: ExternTypeGlobal, Index: 0}},
|
||||||
GlobalSection: []*Global{{}},
|
GlobalSection: []*Global{{}},
|
||||||
},
|
},
|
||||||
|
expectedExports: map[string]api.FunctionDefinition{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "host func",
|
name: "host func",
|
||||||
@@ -43,6 +46,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
|
|||||||
funcType: v_v,
|
funcType: v_v,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
expectedExports: map[string]api.FunctionDefinition{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "without imports",
|
name: "without imports",
|
||||||
@@ -81,20 +85,20 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
|
|||||||
funcType: v_v,
|
funcType: v_v,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedExports: []api.FunctionDefinition{
|
expectedExports: map[string]api.FunctionDefinition{
|
||||||
&FunctionDefinition{
|
"function_index=0": &FunctionDefinition{
|
||||||
index: 0,
|
index: 0,
|
||||||
debugName: ".$0",
|
debugName: ".$0",
|
||||||
exportNames: []string{"function_index=0"},
|
exportNames: []string{"function_index=0"},
|
||||||
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeI32}, Results: []ValueType{ValueTypeV128, ValueTypeI64}},
|
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeI32}, Results: []ValueType{ValueTypeV128, ValueTypeI64}},
|
||||||
},
|
},
|
||||||
&FunctionDefinition{
|
"function_index=1": &FunctionDefinition{
|
||||||
index: 1,
|
index: 1,
|
||||||
exportNames: []string{"function_index=1"},
|
exportNames: []string{"function_index=1"},
|
||||||
debugName: ".$1",
|
debugName: ".$1",
|
||||||
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
|
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
|
||||||
},
|
},
|
||||||
&FunctionDefinition{
|
"function_index=2": &FunctionDefinition{
|
||||||
index: 2,
|
index: 2,
|
||||||
debugName: ".$2",
|
debugName: ".$2",
|
||||||
exportNames: []string{"function_index=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}},
|
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedExports: []api.FunctionDefinition{
|
expectedExports: map[string]api.FunctionDefinition{
|
||||||
&FunctionDefinition{
|
"imported_function": &FunctionDefinition{
|
||||||
index: 0,
|
index: 0,
|
||||||
debugName: ".$0",
|
debugName: ".$0",
|
||||||
importDesc: &[2]string{"", ""},
|
importDesc: &[2]string{"", ""},
|
||||||
exportNames: []string{"imported_function"},
|
exportNames: []string{"imported_function"},
|
||||||
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
|
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
|
||||||
},
|
},
|
||||||
&FunctionDefinition{
|
"function_index=1": &FunctionDefinition{
|
||||||
index: 1,
|
index: 1,
|
||||||
debugName: ".$1",
|
debugName: ".$1",
|
||||||
exportNames: []string{"function_index=1"},
|
exportNames: []string{"function_index=1"},
|
||||||
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeI32}, Results: []ValueType{ValueTypeV128, ValueTypeI64}},
|
funcType: &FunctionType{Params: []ValueType{ValueTypeF64, ValueTypeI32}, Results: []ValueType{ValueTypeV128, ValueTypeI64}},
|
||||||
},
|
},
|
||||||
&FunctionDefinition{
|
"function_index=2": &FunctionDefinition{
|
||||||
index: 2,
|
index: 2,
|
||||||
debugName: ".$2",
|
debugName: ".$2",
|
||||||
exportNames: []string{"function_index=2"},
|
exportNames: []string{"function_index=2"},
|
||||||
@@ -200,6 +204,7 @@ func TestModule_BuildFunctionDefinitions(t *testing.T) {
|
|||||||
expectedImports: []api.FunctionDefinition{
|
expectedImports: []api.FunctionDefinition{
|
||||||
&FunctionDefinition{moduleName: "module", index: 0, debugName: "module.$0", importDesc: &[2]string{"i", "f"}, funcType: v_v},
|
&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