diff --git a/Jint.Tests/Runtime/InteropTests.cs b/Jint.Tests/Runtime/InteropTests.cs
index cf83edd67..3b1593def 100644
--- a/Jint.Tests/Runtime/InteropTests.cs
+++ b/Jint.Tests/Runtime/InteropTests.cs
@@ -3483,4 +3483,66 @@ void Debug(object o)
Assert.Equal("KeyValuePair`2: [test, val]", result[2]);
Assert.Equal("String: test", result[3]);
}
-}
\ No newline at end of file
+
+ 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"]);
+ }
+}
diff --git a/Jint/Options.cs b/Jint/Options.cs
index 9b9bca765..1cee53c6c 100644
--- a/Jint/Options.cs
+++ b/Jint/Options.cs
@@ -364,6 +364,13 @@ public class InteropOptions
/// Whether the engine should throw an error when a member is not found on a CLR object. Defaults to false.
///
public bool ThrowOnUnresolvedMember { get; set; }
+
+ ///
+ /// Types of CLR members reported by when enumerating properties/serializing .
+ /// Supported values are: , , .
+ /// All other values are ignored.
+ ///
+ public MemberTypes ObjectWrapperReportedMemberTypes { get; set; } = MemberTypes.Field | MemberTypes.Property | MemberTypes.Method;
}
public class ConstraintOptions
diff --git a/Jint/Runtime/Interop/ObjectWrapper.cs b/Jint/Runtime/Interop/ObjectWrapper.cs
index b79f3afe3..0846b09b2 100644
--- a/Jint/Runtime/Interop/ObjectWrapper.cs
+++ b/Jint/Runtime/Interop/ObjectWrapper.cs
@@ -225,7 +225,7 @@ public override IEnumerable> GetOwnPro
yield return new KeyValuePair(key, GetOwnProperty(key));
}
}
-
+
private IEnumerable EnumerateOwnPropertyKeys(Types types)
{
// prefer object order, add possible other properties after
@@ -235,8 +235,7 @@ private IEnumerable EnumerateOwnPropertyKeys(Types types)
var keys = (ICollection) _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 @@ private IEnumerable EnumerateOwnPropertyKeys(Types types)
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);
+ }
}
}
}