Pass correct api.Module to host functions (#1213)
Fixes #1211 Previously, host functions are getting api.Module for the "originating" module, which is the module for api.Function currently invoked, except that the api.Module is modified by withMemory with the caller's memory instance, therefore there haven't been no problem for most cases. The only issues were the methods besides Memory() of api.Module, and this commit fixes them. Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
This commit is contained in:
@@ -47,6 +47,7 @@ var tests = map[string]func(t *testing.T, r wazero.Runtime){
|
||||
"un-signed extend global": testGlobalExtend,
|
||||
"user-defined primitive in host func": testUserDefinedPrimitiveHostFunc,
|
||||
"ensures invocations terminate on module close": testEnsureTerminationOnClose,
|
||||
"call host function indirectly": callHostFunctionIndirect,
|
||||
}
|
||||
|
||||
func TestEngineCompiler(t *testing.T) {
|
||||
@@ -479,6 +480,62 @@ func testHostFunctionNumericParameter(t *testing.T, r wazero.Runtime) {
|
||||
}
|
||||
}
|
||||
|
||||
func callHostFunctionIndirect(t *testing.T, r wazero.Runtime) {
|
||||
// With the following call graph,
|
||||
// originWasmModule -- call --> importingWasmModule -- call --> hostModule
|
||||
// this ensures that hostModule's hostFn only has access importingWasmModule, not originWasmModule.
|
||||
|
||||
const hostModule, importingWasmModule, originWasmModule = "host", "importing", "origin"
|
||||
const hostFn, importingWasmModuleFn, originModuleFn = "host_fn", "call_host_func", "origin"
|
||||
importingModule := &wasm.Module{
|
||||
TypeSection: []*wasm.FunctionType{{Params: []wasm.ValueType{}, Results: []wasm.ValueType{}}},
|
||||
ImportSection: []*wasm.Import{{Module: hostModule, Name: hostFn, Type: wasm.ExternTypeFunc, DescFunc: 0}},
|
||||
FunctionSection: []wasm.Index{0},
|
||||
ExportSection: []*wasm.Export{{Name: importingWasmModuleFn, Type: wasm.ExternTypeFunc, Index: 1}},
|
||||
CodeSection: []*wasm.Code{{Body: []byte{wasm.OpcodeCall, 0, wasm.OpcodeEnd}}},
|
||||
NameSection: &wasm.NameSection{ModuleName: importingWasmModule},
|
||||
}
|
||||
|
||||
originModule := &wasm.Module{
|
||||
TypeSection: []*wasm.FunctionType{{Params: []wasm.ValueType{}, Results: []wasm.ValueType{}}},
|
||||
ImportSection: []*wasm.Import{{Module: importingWasmModule, Name: importingWasmModuleFn, Type: wasm.ExternTypeFunc, DescFunc: 0}},
|
||||
FunctionSection: []wasm.Index{0},
|
||||
ExportSection: []*wasm.Export{{Name: "origin", Type: wasm.ExternTypeFunc, Index: 1}},
|
||||
CodeSection: []*wasm.Code{{Body: []byte{wasm.OpcodeCall, 0, wasm.OpcodeEnd}}},
|
||||
NameSection: &wasm.NameSection{ModuleName: originWasmModule},
|
||||
}
|
||||
|
||||
require.NoError(t, importingModule.Validate(api.CoreFeaturesV2))
|
||||
require.NoError(t, originModule.Validate(api.CoreFeaturesV2))
|
||||
importingModuleBytes := binaryencoding.EncodeModule(importingModule)
|
||||
originModuleBytes := binaryencoding.EncodeModule(originModule)
|
||||
|
||||
var originInst, importingInst api.Module
|
||||
_, err := r.NewHostModuleBuilder(hostModule).
|
||||
NewFunctionBuilder().
|
||||
WithFunc(func(ctx context.Context, mod api.Module) {
|
||||
// Module must be the caller (importing module), not the origin.
|
||||
require.Equal(t, mod, importingInst)
|
||||
require.NotEqual(t, mod, originInst)
|
||||
// Name must be the caller, not origin.
|
||||
require.Equal(t, importingWasmModule, mod.Name())
|
||||
}).
|
||||
Export(hostFn).
|
||||
Instantiate(testCtx)
|
||||
require.NoError(t, err)
|
||||
|
||||
importingInst, err = r.Instantiate(testCtx, importingModuleBytes)
|
||||
require.NoError(t, err)
|
||||
originInst, err = r.Instantiate(testCtx, originModuleBytes)
|
||||
require.NoError(t, err)
|
||||
|
||||
originFn := originInst.ExportedFunction(originModuleFn)
|
||||
require.NotNil(t, originFn)
|
||||
|
||||
_, err = originFn.Call(testCtx)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func callReturnImportWasm(t *testing.T, importedModule, importingModule string, vt wasm.ValueType) []byte {
|
||||
// test an imported function by re-exporting it
|
||||
module := &wasm.Module{
|
||||
|
||||
Reference in New Issue
Block a user