mirror of
https://github.com/robertkrimen/otto
synced 2025-10-12 20:27:30 +08:00
Add ability to call struct methods
This fixes #60 This is incompatible with go 1.0.3
This commit is contained in:
parent
661a61c5a0
commit
07737f86b9
|
@ -14,6 +14,34 @@ type testStruct struct {
|
|||
Jkl interface{}
|
||||
}
|
||||
|
||||
func (t *testStruct) FuncPointerReciever() string {
|
||||
return "abc"
|
||||
}
|
||||
|
||||
func (t testStruct) FuncNoArgsNoRet() {
|
||||
return
|
||||
}
|
||||
|
||||
func (t testStruct) FuncNoArgs() string {
|
||||
return "abc"
|
||||
}
|
||||
|
||||
func (t testStruct) FuncNoArgsMultRet() (string, error) {
|
||||
return "def", nil
|
||||
}
|
||||
|
||||
func (t testStruct) FuncOneArgs(a string) string {
|
||||
return a
|
||||
}
|
||||
|
||||
func (t testStruct) FuncMultArgs(a, b string) string {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func (t testStruct) FuncVarArgs(as ...string) int {
|
||||
return len(as)
|
||||
}
|
||||
|
||||
func TestReflect(t *testing.T) {
|
||||
Terst(t)
|
||||
|
||||
|
@ -35,6 +63,10 @@ func Test_reflectStruct(t *testing.T) {
|
|||
abc := &testStruct{}
|
||||
failSet("abc", abc)
|
||||
|
||||
test(`
|
||||
abc.FuncPointerReciever();
|
||||
`, "abc")
|
||||
|
||||
test(`
|
||||
[ abc.Abc, abc.Ghi ];
|
||||
`, "false,")
|
||||
|
@ -78,6 +110,26 @@ func Test_reflectStruct(t *testing.T) {
|
|||
[ abc.Def, abc.abc ];
|
||||
`, "451,")
|
||||
Is(abc.Def, 451)
|
||||
|
||||
test(`
|
||||
abc.FuncNoArgsNoRet();
|
||||
`, "undefined")
|
||||
test(`
|
||||
abc.FuncNoArgs();
|
||||
`, "abc")
|
||||
test(`
|
||||
abc.FuncOneArgs("abc");
|
||||
`, "abc")
|
||||
test(`
|
||||
abc.FuncMultArgs("abc", "def");
|
||||
`, "abcdef")
|
||||
test(`
|
||||
abc.FuncVarArgs("abc", "def", "ghi");
|
||||
`, "3")
|
||||
|
||||
test(`raise:
|
||||
abc.FuncNoArgsMultRet();
|
||||
`, "TypeError")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
15
runtime.go
15
runtime.go
|
@ -322,6 +322,21 @@ func (self *_runtime) toValue(value interface{}) Value {
|
|||
case reflect.Array:
|
||||
return toValue_object(self.newGoArray(value))
|
||||
}
|
||||
case reflect.Func:
|
||||
return toValue_object(self.newNativeFunction(func(call FunctionCall) Value {
|
||||
args := make([]reflect.Value, len(call.ArgumentList))
|
||||
for i, a := range call.ArgumentList {
|
||||
args[i] = reflect.ValueOf(a.export())
|
||||
}
|
||||
|
||||
retvals := value.Call(args)
|
||||
if len(retvals) > 1 {
|
||||
panic(newTypeError())
|
||||
} else if len(retvals) == 1 {
|
||||
return toValue(retvals[0].Interface())
|
||||
}
|
||||
return UndefinedValue()
|
||||
}))
|
||||
case reflect.Struct:
|
||||
return toValue_object(self.newGoStructObject(value))
|
||||
case reflect.Map:
|
||||
|
|
|
@ -27,13 +27,25 @@ func _newGoStructObject(value reflect.Value) *_goStructObject {
|
|||
}
|
||||
|
||||
func (self _goStructObject) getValue(name string) reflect.Value {
|
||||
return reflect.Indirect(self.value).FieldByName(name)
|
||||
if field := reflect.Indirect(self.value).FieldByName(name); (field != reflect.Value{}) {
|
||||
return field
|
||||
}
|
||||
|
||||
if method := self.value.MethodByName(name); (method != reflect.Value{}) {
|
||||
return method
|
||||
}
|
||||
|
||||
return reflect.Value{}
|
||||
}
|
||||
|
||||
func (self _goStructObject) field(name string) (reflect.StructField, bool) {
|
||||
return reflect.Indirect(self.value).Type().FieldByName(name)
|
||||
}
|
||||
|
||||
func (self _goStructObject) method(name string) (reflect.Method, bool) {
|
||||
return reflect.Indirect(self.value).Type().MethodByName(name)
|
||||
}
|
||||
|
||||
func (self _goStructObject) setValue(name string, value Value) bool {
|
||||
field, exists := self.field(name)
|
||||
if !exists {
|
||||
|
@ -60,10 +72,17 @@ func goStructGetOwnProperty(self *_object, name string) *_property {
|
|||
|
||||
func goStructEnumerate(self *_object, all bool, each func(string) bool) {
|
||||
object := self.value.(*_goStructObject)
|
||||
count := object.value.NumField()
|
||||
type_ := object.value.Type()
|
||||
for index := 0; index < count; index++ {
|
||||
if !each(type_.Field(index).Name) {
|
||||
|
||||
// Enumerate fields
|
||||
for index := 0; index < reflect.Indirect(object.value).NumField(); index++ {
|
||||
if !each(reflect.Indirect(object.value).Type().Field(index).Name) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Enumerate methods
|
||||
for index := 0; index < object.value.NumMethod(); index++ {
|
||||
if !each(object.value.Type().Method(index).Name) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user