Browse Source

Removed erroneous IsExported() calls, because these are js names which may be mapped. Closes #114

Dmitry Panov 6 years ago
parent
commit
aa89e6a4c7
2 changed files with 83 additions and 25 deletions
  1. 18 23
      object_goreflect.go
  2. 65 2
      object_goreflect_test.go

+ 18 - 23
object_goreflect.go

@@ -18,7 +18,7 @@ type FieldNameMapper interface {
 	// If this method returns "" the field becomes hidden.
 	FieldName(t reflect.Type, f reflect.StructField) string
 
-	// FieldName returns a JavaScript name for the given method in the given type.
+	// MethodName returns a JavaScript name for the given method in the given type.
 	// If this method returns "" the method becomes hidden.
 	MethodName(t reflect.Type, m reflect.Method) string
 }
@@ -216,25 +216,23 @@ func (r *Runtime) checkHostObjectPropertyDescr(name string, descr propertyDescr,
 }
 
 func (o *objectGoReflect) defineOwnProperty(n Value, descr propertyDescr, throw bool) bool {
-	name := n.String()
-	if ast.IsExported(name) {
-		if o.value.Kind() == reflect.Struct {
-			if v := o._getField(name); v.IsValid() {
-				if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
-					return false
-				}
-				val := descr.Value
-				if val == nil {
-					val = _undefined
-				}
-				vv, err := o.val.runtime.toReflectValue(val, v.Type())
-				if err != nil {
-					o.val.runtime.typeErrorResult(throw, "Go struct conversion error: %v", err)
-					return false
-				}
-				v.Set(vv)
-				return true
+	if o.value.Kind() == reflect.Struct {
+		name := n.String()
+		if v := o._getField(name); v.IsValid() {
+			if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
+				return false
 			}
+			val := descr.Value
+			if val == nil {
+				val = _undefined
+			}
+			vv, err := o.val.runtime.toReflectValue(val, v.Type())
+			if err != nil {
+				o.val.runtime.typeErrorResult(throw, "Go struct conversion error: %v", err)
+				return false
+			}
+			v.Set(vv)
+			return true
 		}
 	}
 
@@ -242,9 +240,6 @@ func (o *objectGoReflect) defineOwnProperty(n Value, descr propertyDescr, throw
 }
 
 func (o *objectGoReflect) _has(name string) bool {
-	if !ast.IsExported(name) {
-		return false
-	}
 	if o.value.Kind() == reflect.Struct {
 		if v := o._getField(name); v.IsValid() {
 			return true
@@ -508,7 +503,7 @@ func (r *Runtime) typeInfo(t reflect.Type) (info *reflectTypeInfo) {
 	return
 }
 
-// Sets a custom field name mapper for Go types. It can be called at any time, however
+// SetFieldNameMapper sets a custom field name mapper for Go types. It can be called at any time, however
 // the mapping for any given value is fixed at the point of creation.
 // Setting this to nil restores the default behaviour which is all exported fields and methods are mapped to their
 // original unchanged names.

+ 65 - 2
object_goreflect_test.go

@@ -487,14 +487,14 @@ func TestGoReflectEmbeddedStruct(t *testing.T) {
 
 type jsonTagNamer struct{}
 
-func (*jsonTagNamer) FieldName(t reflect.Type, field reflect.StructField) string {
+func (jsonTagNamer) FieldName(t reflect.Type, field reflect.StructField) string {
 	if jsonTag := field.Tag.Get("json"); jsonTag != "" {
 		return jsonTag
 	}
 	return field.Name
 }
 
-func (*jsonTagNamer) MethodName(t reflect.Type, method reflect.Method) string {
+func (jsonTagNamer) MethodName(t reflect.Type, method reflect.Method) string {
 	return method.Name
 }
 
@@ -729,6 +729,69 @@ func TestFieldOverriding(t *testing.T) {
 	}
 }
 
+func TestDefinePropertyUnexportedJsName(t *testing.T) {
+	type T struct {
+		Field      int
+		unexported int
+	}
+
+	vm := New()
+	vm.SetFieldNameMapper(fieldNameMapper1{})
+	vm.Set("f", &T{})
+
+	_, err := vm.RunString(`
+	"use strict";
+	Object.defineProperty(f, "field", {value: 42});
+	if (f.field !== 42) {
+		throw new Error("Unexpected value: " + f.field);
+	}
+	if (f.hasOwnProperty("unexported")) {
+		throw new Error("hasOwnProporty('unexported') is true");
+	}
+	var thrown;
+	try {
+		Object.defineProperty(f, "unexported", {value: 1});
+	} catch (e) {
+		thrown = e;
+	}
+	if (!(thrown instanceof TypeError)) {
+		throw new Error("Unexpected error: ", thrown);
+	}
+	`)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+type fieldNameMapperToLower struct{}
+
+func (fieldNameMapperToLower) FieldName(t reflect.Type, f reflect.StructField) string {
+	return strings.ToLower(f.Name)
+}
+
+func (fieldNameMapperToLower) MethodName(t reflect.Type, m reflect.Method) string {
+	return strings.ToLower(m.Name)
+}
+
+func TestHasOwnPropertyUnexportedJsName(t *testing.T) {
+	vm := New()
+	vm.SetFieldNameMapper(fieldNameMapperToLower{})
+	vm.Set("f", &testGoReflectMethod_O{})
+
+	_, err := vm.RunString(`
+	"use strict";
+	if (!f.hasOwnProperty("test")) {
+		throw new Error("hasOwnProperty('test') returned false");
+	}
+	if (!f.hasOwnProperty("method")) {
+		throw new Error("hasOwnProperty('method') returned false");
+	}
+	`)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
 func BenchmarkGoReflectGet(b *testing.B) {
 	type parent struct {
 		field, Test1, Test2, Test3, Test4, Test5, Test string