Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make own properties for declared only fields and properties configurable #1948

Merged
merged 1 commit into from
Aug 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 21 additions & 20 deletions Jint.Tests/Runtime/Domain/Shape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ namespace Shapes
{
public abstract class Shape
{
public int Id = 123;
public abstract double Perimeter();
public Colors Color { get; set; }

}

public class Circle : Shape
Expand All @@ -22,33 +22,34 @@ public Meta()
{
_description = "descp";
}
private string _description;

public string Description
{
get
private string _description;

public string Description
{
return _description;
get
{
return _description;
}
set
{
_description = value;
}
}
set

public enum Usage
{
_description = value;
Public,
Private,
Internal = 11
}
}

public enum Usage
{
Public,
Private,
Internal = 11
}
}

public enum Kind
{
Unit,
Ellipse,
Round = 5
Unit,
Ellipse,
Round = 5
}

public Circle()
Expand All @@ -64,7 +65,7 @@ public Circle(double radius)

public override double Perimeter()
{
return Math.PI*Math.Pow(Radius, 2);
return Math.PI * Math.Pow(Radius, 2);
}
}
}
16 changes: 16 additions & 0 deletions Jint.Tests/Runtime/InteropTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3585,4 +3585,20 @@ public void ShouldNotThrowOnInspectingClrClassFunction()

decl.Should().BeNull();
}

[Fact]
public void StringifyShouldIncludeInheritedFieldsAndProperties()
{
var engine = new Engine();
engine.SetValue("c", new Circle(12.34));
engine.Evaluate("JSON.stringify(c)").ToString().Should().Be("{\"Radius\":12.34,\"Color\":0,\"Id\":123}");


engine = new Engine(options =>
{
options.Interop.ObjectWrapperReportOnlyDeclaredMembers = true;
});
engine.SetValue("c", new Circle(12.34));
engine.Evaluate("JSON.stringify(c)").ToString().Should().Be("{\"Radius\":12.34}");
}
}
7 changes: 7 additions & 0 deletions Jint/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,13 @@ public class InteropOptions
/// All other values are ignored.
/// </summary>
public MemberTypes ObjectWrapperReportedMemberTypes { get; set; } = MemberTypes.Field | MemberTypes.Property | MemberTypes.Method;

/// <summary>
/// Whether object wrapper should only report members that are declared on the object type itself, not inherited members. Defaults to false.
/// This is different from JS logic where only object's own members are reported and not prototypes.
/// </summary>
/// <remarks>This configuration does not affect methods, only methods declared in type itself will be reported.</remarks>
public bool ObjectWrapperReportOnlyDeclaredMembers { get; set; }
}

public class ConstraintOptions
Expand Down
20 changes: 13 additions & 7 deletions Jint/Runtime/Interop/ObjectWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,18 @@ private IEnumerable<JsValue> EnumerateOwnPropertyKeys(Types types)
}
else if (includeStrings)
{
var interopOptions = _engine.Options.Interop;

// we take public properties, fields and methods
const BindingFlags BindingFlags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public;
var bindingFlags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public;
if (interopOptions.ObjectWrapperReportOnlyDeclaredMembers)
{
bindingFlags |= BindingFlags.DeclaredOnly;
}

if ((_engine.Options.Interop.ObjectWrapperReportedMemberTypes & MemberTypes.Property) == MemberTypes.Property)
if ((interopOptions.ObjectWrapperReportedMemberTypes & MemberTypes.Property) == MemberTypes.Property)
{
foreach (var p in ClrType.GetProperties(BindingFlags))
foreach (var p in ClrType.GetProperties(bindingFlags))
{
var indexParameters = p.GetIndexParameters();
if (indexParameters.Length == 0)
Expand All @@ -268,17 +274,17 @@ private IEnumerable<JsValue> EnumerateOwnPropertyKeys(Types types)
}
}

if ((_engine.Options.Interop.ObjectWrapperReportedMemberTypes & MemberTypes.Field) == MemberTypes.Field)
if ((interopOptions.ObjectWrapperReportedMemberTypes & MemberTypes.Field) == MemberTypes.Field)
{
foreach (var f in ClrType.GetFields(BindingFlags | BindingFlags.DeclaredOnly))
foreach (var f in ClrType.GetFields(bindingFlags))
{
yield return JsString.Create(f.Name);
}
}

if ((_engine.Options.Interop.ObjectWrapperReportedMemberTypes & MemberTypes.Method) == MemberTypes.Method)
if ((interopOptions.ObjectWrapperReportedMemberTypes & MemberTypes.Method) == MemberTypes.Method)
{
foreach (var m in ClrType.GetMethods(BindingFlags | BindingFlags.DeclaredOnly))
foreach (var m in ClrType.GetMethods(bindingFlags | BindingFlags.DeclaredOnly))
{
if (m.IsSpecialName)
{
Expand Down