Explorar el Código

Add ObjectWrapperReportedMemberTypes to Options (#1947)

---------

Co-authored-by: Marko Lahma <[email protected]>
Matěj Štágl hace 11 meses
padre
commit
2e7ec9d441
Se han modificado 3 ficheros con 101 adiciones y 15 borrados
  1. 63 1
      Jint.Tests/Runtime/InteropTests.cs
  2. 7 0
      Jint/Options.cs
  3. 31 14
      Jint/Runtime/Interop/ObjectWrapper.cs

+ 63 - 1
Jint.Tests/Runtime/InteropTests.cs

@@ -3483,4 +3483,66 @@ try {
         Assert.Equal("KeyValuePair`2: [test, val]", result[2]);
         Assert.Equal("String: test", result[3]);
     }
-}
+
+    private class ClrMembersVisibilityTestClass
+    {
+        public int A { get; set; } = 10;
+
+        public int F()
+        {
+            return 4;
+        }
+    }
+
+    [Fact]
+    public void ShouldNotSeeClrMethods()
+    {
+        var engine = new Engine(opt =>
+        {
+            opt.Interop.ObjectWrapperReportedMemberTypes = MemberTypes.Field | MemberTypes.Property;
+        });
+        
+        engine.SetValue("clrInstance", new ClrMembersVisibilityTestClass());
+        
+         var val = engine.GetValue("clrInstance");
+
+         var obj = val.AsObject();
+         var props = obj.GetOwnProperties().Select(x => x.Key.ToString()).ToList();
+         
+         props.Should().BeEquivalentTo(["A"]);
+    }
+    
+    [Fact]
+    public void ShouldSeeClrMethods()
+    {
+        var engine = new Engine();
+        
+        engine.SetValue("clrInstance", new ClrMembersVisibilityTestClass());
+        
+        var val = engine.GetValue("clrInstance");
+        var obj = val.AsObject();
+        var props = obj.GetOwnProperties().Select(x => x.Key.ToString()).ToList();
+
+        props.Should().BeEquivalentTo(["A", "F"]);
+    }
+    
+    private class ClrMembersVisibilityTestClass2
+    {
+        public int Get_A { get; set; } = 5;
+    }
+    
+    [Fact]
+    public void ShouldSeeClrMethods2()
+    {
+        var engine = new Engine();
+        
+        engine.SetValue("clrInstance", new ClrMembersVisibilityTestClass2());
+        
+        var val = engine.GetValue("clrInstance");
+
+        var obj = val.AsObject();
+        var props = obj.GetOwnProperties().Select(x => x.Key.ToString()).ToList();
+         
+        props.Should().BeEquivalentTo(["Get_A"]);
+    }
+}

+ 7 - 0
Jint/Options.cs

@@ -364,6 +364,13 @@ public class Options
         /// Whether the engine should throw an error when a member is not found on a CLR object. Defaults to false.
         /// </summary>
         public bool ThrowOnUnresolvedMember { get; set; }
+
+        /// <summary>
+        /// Types of CLR members reported by <see cref="ObjectWrapper"/> when enumerating properties/serializing <see cref="ObjectWrapper.ToObject"/>.
+        /// Supported values are: <see cref="MemberTypes.Field"/>, <see cref="MemberTypes.Property"/>, <see cref="MemberTypes.Method"/>.
+        /// All other values are ignored.
+        /// </summary>
+        public MemberTypes ObjectWrapperReportedMemberTypes { get; set; } = MemberTypes.Field | MemberTypes.Property | MemberTypes.Method;
     }
 
     public class ConstraintOptions

+ 31 - 14
Jint/Runtime/Interop/ObjectWrapper.cs

@@ -225,7 +225,7 @@ public class ObjectWrapper : ObjectInstance, IObjectWrapper, IEquatable<ObjectWr
             yield return new KeyValuePair<JsValue, PropertyDescriptor>(key, GetOwnProperty(key));
         }
     }
-
+    
     private IEnumerable<JsValue> EnumerateOwnPropertyKeys(Types types)
     {
         // prefer object order, add possible other properties after
@@ -235,8 +235,7 @@ public class ObjectWrapper : ObjectInstance, IObjectWrapper, IEquatable<ObjectWr
             var keys = (ICollection<string>) _typeDescriptor.KeysAccessor!.GetValue(Target)!;
             foreach (var key in keys)
             {
-                var jsString = JsString.Create(key);
-                yield return jsString;
+                yield return JsString.Create(key);
             }
         }
         else if (includeStrings && Target is IDictionary dictionary)
@@ -248,28 +247,46 @@ public class ObjectWrapper : ObjectInstance, IObjectWrapper, IEquatable<ObjectWr
                 if (stringKey is not null
                     || _engine.TypeConverter.TryConvert(key, typeof(string), CultureInfo.InvariantCulture, out stringKey))
                 {
-                    var jsString = JsString.Create((string) stringKey!);
-                    yield return jsString;
+                    yield return JsString.Create((string) stringKey!);
                 }
             }
         }
         else if (includeStrings)
         {
-            // we take public properties and fields
-            foreach (var p in ClrType.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public))
+            // we take public properties, fields and methods
+            const BindingFlags BindingFlags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public;
+
+            if ((_engine.Options.Interop.ObjectWrapperReportedMemberTypes & MemberTypes.Property) == MemberTypes.Property)
+            {
+                foreach (var p in ClrType.GetProperties(BindingFlags))
+                {
+                    var indexParameters = p.GetIndexParameters();
+                    if (indexParameters.Length == 0)
+                    {
+                        yield return JsString.Create(p.Name);
+                    }
+                }
+            }
+
+            if ((_engine.Options.Interop.ObjectWrapperReportedMemberTypes & MemberTypes.Field) == MemberTypes.Field)
             {
-                var indexParameters = p.GetIndexParameters();
-                if (indexParameters.Length == 0)
+                foreach (var f in ClrType.GetFields(BindingFlags | BindingFlags.DeclaredOnly))
                 {
-                    var jsString = JsString.Create(p.Name);
-                    yield return jsString;
+                    yield return JsString.Create(f.Name);
                 }
             }
 
-            foreach (var f in ClrType.GetFields(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public))
+            if ((_engine.Options.Interop.ObjectWrapperReportedMemberTypes & MemberTypes.Method) == MemberTypes.Method)
             {
-                var jsString = JsString.Create(f.Name);
-                yield return jsString;
+                foreach (var m in ClrType.GetMethods(BindingFlags | BindingFlags.DeclaredOnly))
+                {
+                    if (m.IsSpecialName)
+                    {
+                        continue;
+                    }
+
+                    yield return JsString.Create(m.Name);
+                }
             }
         }
     }