mirror of
https://github.com/robertkrimen/otto
synced 2025-10-12 20:27:30 +08:00
use consistent field access rules across read/write and argument conversion
This commit is contained in:
parent
15f95af6e7
commit
0f57984957
66
runtime.go
66
runtime.go
|
@ -285,6 +285,38 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value {
|
||||||
panic(self.panicTypeError(fmt.Sprintf("unsupported type %v for numeric conversion", val.Type())))
|
panic(self.panicTypeError(fmt.Sprintf("unsupported type %v for numeric conversion", val.Type())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fieldIndexByName(t reflect.Type, name string) []int {
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
f := t.Field(i)
|
||||||
|
|
||||||
|
if !validGoStructName(f.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Anonymous {
|
||||||
|
if a := fieldIndexByName(f.Type, name); a != nil {
|
||||||
|
return append([]int{i}, a...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if a := strings.SplitN(f.Tag.Get("json"), ",", 2); a[0] != "" {
|
||||||
|
if a[0] == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if a[0] == name {
|
||||||
|
return []int{i}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Name == name {
|
||||||
|
return []int{i}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var typeOfValue = reflect.TypeOf(Value{})
|
var typeOfValue = reflect.TypeOf(Value{})
|
||||||
|
|
||||||
// convertCallParameter converts request val to type t if possible.
|
// convertCallParameter converts request val to type t if possible.
|
||||||
|
@ -467,41 +499,15 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu
|
||||||
s := reflect.New(t)
|
s := reflect.New(t)
|
||||||
|
|
||||||
for _, k := range o.propertyOrder {
|
for _, k := range o.propertyOrder {
|
||||||
var f *reflect.StructField
|
idx := fieldIndexByName(t, k)
|
||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
if idx == nil {
|
||||||
ff := t.Field(i)
|
|
||||||
|
|
||||||
if j := ff.Tag.Get("json"); j != "" {
|
|
||||||
if j == "-" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
a := strings.Split(j, ",")
|
|
||||||
|
|
||||||
if a[0] == k {
|
|
||||||
f = &ff
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ff.Name == k {
|
|
||||||
f = &ff
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.EqualFold(ff.Name, k) {
|
|
||||||
f = &ff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if f == nil {
|
|
||||||
panic(self.panicTypeError("can't convert object; field %q was supplied but does not exist on target %v", k, t))
|
panic(self.panicTypeError("can't convert object; field %q was supplied but does not exist on target %v", k, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
ss := s
|
ss := s
|
||||||
|
|
||||||
for _, i := range f.Index {
|
for _, i := range idx {
|
||||||
if ss.Kind() == reflect.Ptr {
|
if ss.Kind() == reflect.Ptr {
|
||||||
if ss.IsNil() {
|
if ss.IsNil() {
|
||||||
if !ss.CanSet() {
|
if !ss.CanSet() {
|
||||||
|
@ -572,7 +578,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu
|
||||||
s = v.Class()
|
s = v.Class()
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(self.panicTypeError("can't convert from %q to %q", s, t.String()))
|
panic(self.panicTypeError("can't convert from %q to %q", s, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) toValue(value interface{}) Value {
|
func (self *_runtime) toValue(value interface{}) Value {
|
||||||
|
|
|
@ -36,6 +36,10 @@ func _newGoStructObject(value reflect.Value) *_goStructObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _goStructObject) getValue(name string) reflect.Value {
|
func (self _goStructObject) getValue(name string) reflect.Value {
|
||||||
|
if f, ok := self.field(name); ok {
|
||||||
|
return reflect.Indirect(self.value).FieldByIndex(f.Index)
|
||||||
|
}
|
||||||
|
|
||||||
if validGoStructName(name) {
|
if validGoStructName(name) {
|
||||||
// Do not reveal hidden or unexported fields
|
// Do not reveal hidden or unexported fields
|
||||||
if field := reflect.Indirect(self.value).FieldByName(name); (field != reflect.Value{}) {
|
if field := reflect.Indirect(self.value).FieldByName(name); (field != reflect.Value{}) {
|
||||||
|
@ -51,24 +55,26 @@ func (self _goStructObject) getValue(name string) reflect.Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _goStructObject) field(name string) (reflect.StructField, bool) {
|
func (self _goStructObject) field(name string) (reflect.StructField, bool) {
|
||||||
return reflect.Indirect(self.value).Type().FieldByName(name)
|
t := reflect.Indirect(self.value).Type()
|
||||||
|
|
||||||
|
if idx := fieldIndexByName(t, name); len(idx) > 0 {
|
||||||
|
return t.FieldByIndex(idx), true
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.StructField{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _goStructObject) method(name string) (reflect.Method, bool) {
|
func (self _goStructObject) method(name string) (reflect.Method, bool) {
|
||||||
return reflect.Indirect(self.value).Type().MethodByName(name)
|
return reflect.Indirect(self.value).Type().MethodByName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _goStructObject) setValue(name string, value Value) bool {
|
func (self _goStructObject) setValue(rt *_runtime, name string, value Value) bool {
|
||||||
field, exists := self.field(name)
|
if _, exists := self.field(name); !exists {
|
||||||
if !exists {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldValue := self.getValue(name)
|
fieldValue := self.getValue(name)
|
||||||
reflectValue, err := value.toReflectValue(field.Type.Kind())
|
fieldValue.Set(rt.convertCallParameter(value, fieldValue.Type()))
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fieldValue.Set(reflectValue)
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -128,7 +134,7 @@ func goStructCanPut(self *_object, name string) bool {
|
||||||
|
|
||||||
func goStructPut(self *_object, name string, value Value, throw bool) {
|
func goStructPut(self *_object, name string, value Value, throw bool) {
|
||||||
object := self.value.(*_goStructObject)
|
object := self.value.(*_goStructObject)
|
||||||
if object.setValue(name, value) {
|
if object.setValue(self.runtime, name, value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user