Adds ResultNames to HostFunctionBuilder and FunctionDefinition (#887)

This adds ResultNames to HostFunctionBuilder and FunctionDefinition
which helps for multi-results or special-cased ones.

End users can access result names in `FunctionDefinition.ResultNames` or
set for their own host functions via
`HostFunctionBuilder.WithResultNames`. This change adds them for all
built-in functions where result names help.

Most notably, GOOS=js uses `ProxyFunc` to allow logging when a function
returns multiple results. Before, the results were returned without
names: e.g. `11231,1` and now they are named like `n=11231,ok=1`.

We soon plan to allow more visibility in WASI, for example, logging
results that will write to memory offsets. This infrastructure makes it
possible to do that.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Crypt Keeper
2022-12-06 14:30:55 +09:00
committed by GitHub
parent 6c4dd1cfd9
commit af8105ba0e
41 changed files with 813 additions and 823 deletions

View File

@@ -121,6 +121,12 @@ type HostFunctionBuilder interface {
// Note: When defined, names must be provided for all parameters.
WithParameterNames(names ...string) HostFunctionBuilder
// WithResultNames defines optional result names of the function
// signature, e.x. "errno"
//
// Note: When defined, names must be provided for all results.
WithResultNames(names ...string) HostFunctionBuilder
// Export exports this to the HostModuleBuilder as the given name, e.g.
// "random_get"
Export(name string) HostModuleBuilder
@@ -206,7 +212,7 @@ type hostModuleBuilder struct {
r *runtime
moduleName string
nameToGoFunc map[string]interface{}
funcToNames map[string][]string
funcToNames map[string]*wasm.HostFuncNames
}
// NewHostModuleBuilder implements Runtime.NewHostModuleBuilder
@@ -215,16 +221,17 @@ func (r *runtime) NewHostModuleBuilder(moduleName string) HostModuleBuilder {
r: r,
moduleName: moduleName,
nameToGoFunc: map[string]interface{}{},
funcToNames: map[string][]string{},
funcToNames: map[string]*wasm.HostFuncNames{},
}
}
// hostFunctionBuilder implements HostFunctionBuilder
type hostFunctionBuilder struct {
b *hostModuleBuilder
fn interface{}
name string
paramNames []string
b *hostModuleBuilder
fn interface{}
name string
paramNames []string
resultNames []string
}
// WithGoFunction implements HostFunctionBuilder.WithGoFunction
@@ -265,22 +272,32 @@ func (h *hostFunctionBuilder) WithParameterNames(names ...string) HostFunctionBu
return h
}
// WithResultNames implements HostFunctionBuilder.WithResultNames
func (h *hostFunctionBuilder) WithResultNames(names ...string) HostFunctionBuilder {
h.resultNames = names
return h
}
// 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,
}
if fn, ok := h.fn.(*wasm.HostFunc); ok {
if fn.Name == "" {
fn.Name = h.name
fn.Name = names.Name
}
fn.ParamNames = h.paramNames
fn.ParamNames = names.ParamNames
fn.ResultNames = names.ResultNames
fn.ExportNames = []string{exportName}
}
h.b.nameToGoFunc[exportName] = h.fn
if len(h.paramNames) > 0 {
h.b.funcToNames[exportName] = append([]string{h.name}, h.paramNames...)
}
h.b.funcToNames[exportName] = names
return h.b
}