Proxy can mix the called method of the imported structure
rabits opened this issue · comments
Found another interesting behavior: it looks like order of the func fields in proxy matters:
package main
import (
"fmt"
"reflect"
"github.com/cosmos72/gomacro/fast"
"github.com/cosmos72/gomacro/imports"
)
type V1Interface interface {
GetName() string
GetType() string
}
type P_V1Interface struct {
Object interface{}
GetType_ func(interface{}) string
GetName_ func(interface{}) string
}
func (P *P_V1Interface) GetName() string {
return P.GetName_(P.Object)
}
func (P *P_V1Interface) GetType() string {
return P.GetType_(P.Object)
}
var script = `package test
type V1Data struct {
Name string
Type string
}
func (t V1Data) GetName() string {
return t.Name
}
func (t V1Data) GetType() string {
return t.Type
}
`
func main() {
interp := fast.New()
imports.Packages["github.com/org/project/pkg/modules"] = imports.Package{
Binds: map[string]reflect.Value{},
Types: map[string]reflect.Type{
"V1Interface": reflect.TypeOf((*V1Interface)(nil)).Elem(),
},
Proxies: map[string]reflect.Type{
"V1Interface": reflect.TypeOf((*P_V1Interface)(nil)).Elem(),
},
Untypeds: map[string]string{},
Wrappers: map[string][]string{},
}
interp.ImportPackage("", "github.com/org/project/pkg/modules")
interp.Eval(script)
intv, _ := interp.Eval1(`modules.V1Interface(V1Data{Name: "name_data", Type: "type_data"})`)
intp := intv.Interface().(V1Interface)
fmt.Printf("Name: %v\n", intp.GetName())
fmt.Printf("Type: %v\n", intp.GetType())
}
This example will print:
Name: type_data
Type: name_data
And if we will switch the order in proxy:
...
type P_V1Interface struct {
Object interface{}
GetName_ func(interface{}) string
GetType_ func(interface{}) string
}
...
The result will be just fine:
Name: name_data
Type: type_data
Seems the other modifications are not affecting the values - in scripts it doesn't matter so if compiled proxy was done properly it will be safe for scripts. But also it could call the function with the wrong arguments - and here is just luck helped me to debug what was wrong.
Nice catch @rabits !
I guess this issue never emerged before because imports.Package
structs usually appear only in autogenerated code (i.e. sources generated by the various gomacro imports mechanisms), rather than in user-written sources.
I will add a consistency check when gomacro loads the interface proxies contained in an imports.Package
- it will check that fields of a proxy (beyond Object_
, which must be the first field) are in the same order as interface methods retrieved with reflect.Type.Method(int)
which currently means they must be in alphabetic (to be exact, lexicographic) order.
Fixed in commit 5a01d1f
Great! Thank you very much)