Skip to content

Commit

Permalink
Improve interop finding of properties in derived types (#1969)
Browse files Browse the repository at this point in the history
  • Loading branch information
mspertus authored Sep 23, 2024
1 parent 6b2d622 commit e67e58a
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
41 changes: 41 additions & 0 deletions Jint.Tests/Runtime/InteropTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3624,4 +3624,45 @@ public void StringifyShouldIncludeInheritedFieldsAndProperties()
engine.SetValue("c", new Circle(12.34));
engine.Evaluate("JSON.stringify(c)").ToString().Should().Be("{\"Radius\":12.34,\"Color\":0,\"Id\":123}");
}

public class Animal
{
public virtual string name { get; set; } = "animal";
}

public class Elephant : Animal
{
public override string name { get; set; } = "elephant";
public int earSize = 5;
}

public class Lion : Animal
{
public override string name { get; set; } = "lion";
public int maneLength = 10;
}

public class Zoo
{
public Animal king { get => (new Animal[] { new Lion() })[0]; }
public Animal[] animals { get => new Animal[] { new Lion(), new Elephant() }; }
}

[Fact]
public void CanFindDerivedPropertiesFail() // Fails in 4.01 but success in 2.11
{
var engine = new Engine();
engine.SetValue("zoo", new Zoo());
var kingManeLength = engine.Evaluate("zoo.King.maneLength");
Assert.Equal(10, kingManeLength.AsNumber());
}

[Fact]
public void CanFindDerivedPropertiesSucceed() // Similar case that continues to succeed
{
var engine = new Engine();
engine.SetValue("zoo", new Zoo());
var lionManeLength = engine.Evaluate("zoo.animals[0].maneLength");
Assert.Equal(10, lionManeLength.AsNumber());
}
}
4 changes: 4 additions & 0 deletions Jint/Runtime/Interop/ObjectWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,10 @@ private PropertyDescriptor GetOwnProperty(JsValue property, bool mustBeReadable,
}

var accessor = _engine.Options.Interop.TypeResolver.GetAccessor(_engine, ClrType, member, mustBeReadable, mustBeWritable);
if (accessor == ConstantValueAccessor.NullAccessor && ClrType != Target.GetType())
{
accessor = _engine.Options.Interop.TypeResolver.GetAccessor(_engine, Target.GetType(), member, mustBeReadable, mustBeWritable);
}
var descriptor = accessor.CreatePropertyDescriptor(_engine, Target, member, enumerable: !isDictionary);
if (!isDictionary
&& !ReferenceEquals(descriptor, PropertyDescriptor.Undefined)
Expand Down

0 comments on commit e67e58a

Please sign in to comment.