diff --git a/object_goarray_reflect.go b/object_goarray_reflect.go index 9b6998af..92f9e958 100644 --- a/object_goarray_reflect.go +++ b/object_goarray_reflect.go @@ -50,7 +50,7 @@ func (o *objectGoArrayReflect) _getIdx(idx int) Value { if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && v.IsNil() { return _null } - return o.val.runtime.ToValue(v.Interface()) + return o.val.runtime.toValue(v.Interface(), v) } func (o *objectGoArrayReflect) getIdx(idx valueInt, receiver Value) Value { diff --git a/object_gomap_reflect.go b/object_gomap_reflect.go index 2734acfb..324e68fe 100644 --- a/object_gomap_reflect.go +++ b/object_gomap_reflect.go @@ -41,7 +41,7 @@ func (o *objectGoMapReflect) _get(n Value) Value { return nil } if v := o.value.MapIndex(key); v.IsValid() { - return o.val.runtime.ToValue(v.Interface()) + return o.val.runtime.toValue(v.Interface(), v) } return nil @@ -53,7 +53,7 @@ func (o *objectGoMapReflect) _getStr(name string) Value { return nil } if v := o.value.MapIndex(key); v.IsValid() { - return o.val.runtime.ToValue(v.Interface()) + return o.val.runtime.toValue(v.Interface(), v) } return nil diff --git a/object_goreflect.go b/object_goreflect.go index 86e8fb54..0fde9071 100644 --- a/object_goreflect.go +++ b/object_goreflect.go @@ -155,22 +155,15 @@ func (o *objectGoReflect) _getMethod(jsName string) reflect.Value { return reflect.Value{} } -func (o *objectGoReflect) getAddr(v reflect.Value) reflect.Value { - if (v.Kind() == reflect.Struct || v.Kind() == reflect.Slice) && v.CanAddr() { - return v.Addr() - } - return v -} - func (o *objectGoReflect) _get(name string) Value { if o.value.Kind() == reflect.Struct { if v := o._getField(name); v.IsValid() { - return o.val.runtime.ToValue(o.getAddr(v).Interface()) + return o.val.runtime.toValue(v.Interface(), v) } } if v := o._getMethod(name); v.IsValid() { - return o.val.runtime.ToValue(v.Interface()) + return o.val.runtime.toValue(v.Interface(), v) } return nil @@ -181,7 +174,7 @@ func (o *objectGoReflect) getOwnPropStr(name unistring.String) Value { if o.value.Kind() == reflect.Struct { if v := o._getField(n); v.IsValid() { return &valueProperty{ - value: o.val.runtime.ToValue(o.getAddr(v).Interface()), + value: o.val.runtime.toValue(v.Interface(), v), writable: v.CanSet(), enumerable: true, } @@ -190,7 +183,7 @@ func (o *objectGoReflect) getOwnPropStr(name unistring.String) Value { if v := o._getMethod(n); v.IsValid() { return &valueProperty{ - value: o.val.runtime.ToValue(v.Interface()), + value: o.val.runtime.toValue(v.Interface(), v), enumerable: true, } } diff --git a/runtime.go b/runtime.go index 86a16f13..eace4d61 100644 --- a/runtime.go +++ b/runtime.go @@ -1624,6 +1624,10 @@ Note that the underlying type is not lost, calling Export() returns the original reflect based types. */ func (r *Runtime) ToValue(i interface{}) Value { + return r.toValue(i, reflect.Value{}) +} + +func (r *Runtime) toValue(i interface{}, origValue reflect.Value) Value { switch i := i.(type) { case nil: return _null @@ -1739,7 +1743,18 @@ func (r *Runtime) ToValue(i interface{}) Value { return obj } - origValue := reflect.ValueOf(i) + if !origValue.IsValid() { + origValue = reflect.ValueOf(i) + } else { + // If origValue was a result of an Index(), or Field(), or such, its Kind may be Interface: + // a := []interface{}{(*S)(nil)} + // a0 := reflect.ValueOf(a).Index(0) // a0.Kind() is reflect.Interface + // a1 := reflect.ValueOf(a[0]) // a1.Kind() is reflect.Ptr + // Need to "dereference" it to make it consistent with plain value being passed. + for origValue.Kind() == reflect.Interface { + origValue = origValue.Elem() + } + } value := origValue for value.Kind() == reflect.Ptr { value = reflect.Indirect(value)