Makes host function index insertion order (#1370)
This makes host functions index consistently on insertion order, rather than lexicographic order. This helps with ABI such as Emscripten, which need an expected order. This also constrains the internal code around host functions to only one export name. More than one was never used. By restricting this, logic is simpler and smaller. Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
76
builder.go
76
builder.go
@@ -146,7 +146,7 @@ type HostFunctionBuilder interface {
|
||||
// defer r.Close(ctx) // This closes everything this Runtime created.
|
||||
//
|
||||
// hello := func() {
|
||||
// fmt.Fprintln(stdout, "hello!")
|
||||
// println("hello!")
|
||||
// }
|
||||
// env, _ := r.NewHostModuleBuilder("env").
|
||||
// NewFunctionBuilder().WithFunc(hello).Export("hello").
|
||||
@@ -170,8 +170,8 @@ type HostFunctionBuilder interface {
|
||||
// chaining.
|
||||
// - methods do not return errors, to allow chaining. Any validation errors
|
||||
// are deferred until Compile.
|
||||
// - Insertion order is not retained. Anything defined by this builder is
|
||||
// sorted lexicographically on Compile.
|
||||
// - Functions are indexed in order of calls to NewFunctionBuilder as
|
||||
// insertion ordering is needed by ABI such as Emscripten (invoke_*).
|
||||
type HostModuleBuilder interface {
|
||||
// Note: until golang/go#5860, we can't use example tests to embed code in interface godocs.
|
||||
|
||||
@@ -191,7 +191,7 @@ type HostModuleBuilder interface {
|
||||
// defer r.Close(ctx) // This closes everything this Runtime created.
|
||||
//
|
||||
// hello := func() {
|
||||
// fmt.Fprintln(stdout, "hello!")
|
||||
// println("hello!")
|
||||
// }
|
||||
// env, _ := r.NewHostModuleBuilder("env").
|
||||
// NewFunctionBuilder().WithFunc(hello).Export("hello").
|
||||
@@ -207,19 +207,18 @@ type HostModuleBuilder interface {
|
||||
|
||||
// hostModuleBuilder implements HostModuleBuilder
|
||||
type hostModuleBuilder struct {
|
||||
r *runtime
|
||||
moduleName string
|
||||
nameToGoFunc map[string]interface{}
|
||||
funcToNames map[string]*wasm.HostFuncNames
|
||||
r *runtime
|
||||
moduleName string
|
||||
exportNames []string
|
||||
nameToHostFunc map[string]*wasm.HostFunc
|
||||
}
|
||||
|
||||
// NewHostModuleBuilder implements Runtime.NewHostModuleBuilder
|
||||
func (r *runtime) NewHostModuleBuilder(moduleName string) HostModuleBuilder {
|
||||
return &hostModuleBuilder{
|
||||
r: r,
|
||||
moduleName: moduleName,
|
||||
nameToGoFunc: map[string]interface{}{},
|
||||
funcToNames: map[string]*wasm.HostFuncNames{},
|
||||
r: r,
|
||||
moduleName: moduleName,
|
||||
nameToHostFunc: map[string]*wasm.HostFunc{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,21 +233,13 @@ type hostFunctionBuilder struct {
|
||||
|
||||
// WithGoFunction implements HostFunctionBuilder.WithGoFunction
|
||||
func (h *hostFunctionBuilder) WithGoFunction(fn api.GoFunction, params, results []api.ValueType) HostFunctionBuilder {
|
||||
h.fn = &wasm.HostFunc{
|
||||
ParamTypes: params,
|
||||
ResultTypes: results,
|
||||
Code: wasm.Code{GoFunc: fn},
|
||||
}
|
||||
h.fn = &wasm.HostFunc{ParamTypes: params, ResultTypes: results, Code: wasm.Code{GoFunc: fn}}
|
||||
return h
|
||||
}
|
||||
|
||||
// WithGoModuleFunction implements HostFunctionBuilder.WithGoModuleFunction
|
||||
func (h *hostFunctionBuilder) WithGoModuleFunction(fn api.GoModuleFunction, params, results []api.ValueType) HostFunctionBuilder {
|
||||
h.fn = &wasm.HostFunc{
|
||||
ParamTypes: params,
|
||||
ResultTypes: results,
|
||||
Code: wasm.Code{GoFunc: fn},
|
||||
}
|
||||
h.fn = &wasm.HostFunc{ParamTypes: params, ResultTypes: results, Code: wasm.Code{GoFunc: fn}}
|
||||
return h
|
||||
}
|
||||
|
||||
@@ -278,30 +269,35 @@ func (h *hostFunctionBuilder) WithResultNames(names ...string) HostFunctionBuild
|
||||
|
||||
// Export implements HostFunctionBuilder.Export
|
||||
func (h *hostFunctionBuilder) Export(exportName string) HostModuleBuilder {
|
||||
if h.name == "" {
|
||||
h.name = exportName
|
||||
}
|
||||
names := &wasm.HostFuncNames{
|
||||
Name: h.name,
|
||||
ParamNames: h.paramNames,
|
||||
ResultNames: h.resultNames,
|
||||
}
|
||||
var hostFn *wasm.HostFunc
|
||||
if fn, ok := h.fn.(*wasm.HostFunc); ok {
|
||||
if fn.Name == "" {
|
||||
fn.Name = names.Name
|
||||
}
|
||||
fn.ParamNames = names.ParamNames
|
||||
fn.ResultNames = names.ResultNames
|
||||
fn.ExportNames = []string{exportName}
|
||||
hostFn = fn
|
||||
} else {
|
||||
hostFn = &wasm.HostFunc{Code: wasm.Code{GoFunc: h.fn}}
|
||||
}
|
||||
h.b.nameToGoFunc[exportName] = h.fn
|
||||
h.b.funcToNames[exportName] = names
|
||||
|
||||
// Assign any names from the builder
|
||||
hostFn.ExportName = exportName
|
||||
if h.name != "" {
|
||||
hostFn.Name = h.name
|
||||
}
|
||||
if len(h.paramNames) != 0 {
|
||||
hostFn.ParamNames = h.paramNames
|
||||
}
|
||||
if len(h.resultNames) != 0 {
|
||||
hostFn.ResultNames = h.resultNames
|
||||
}
|
||||
|
||||
h.b.ExportHostFunc(hostFn)
|
||||
return h.b
|
||||
}
|
||||
|
||||
// ExportHostFunc implements wasm.HostFuncExporter
|
||||
func (b *hostModuleBuilder) ExportHostFunc(fn *wasm.HostFunc) {
|
||||
b.nameToGoFunc[fn.ExportNames[0]] = fn
|
||||
if _, ok := b.nameToHostFunc[fn.ExportName]; !ok { // add a new name
|
||||
b.exportNames = append(b.exportNames, fn.ExportName)
|
||||
}
|
||||
b.nameToHostFunc[fn.ExportName] = fn
|
||||
}
|
||||
|
||||
// NewFunctionBuilder implements HostModuleBuilder.NewFunctionBuilder
|
||||
@@ -311,7 +307,7 @@ func (b *hostModuleBuilder) NewFunctionBuilder() HostFunctionBuilder {
|
||||
|
||||
// Compile implements HostModuleBuilder.Compile
|
||||
func (b *hostModuleBuilder) Compile(ctx context.Context) (CompiledModule, error) {
|
||||
module, err := wasm.NewHostModule(b.moduleName, b.nameToGoFunc, b.funcToNames, b.r.enabledFeatures)
|
||||
module, err := wasm.NewHostModule(b.moduleName, b.exportNames, b.nameToHostFunc, b.r.enabledFeatures)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if err = module.Validate(b.r.enabledFeatures); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user