Skip to content

Commit

Permalink
Include interface's extended interfaces in interop property search (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma authored Oct 22, 2023
1 parent f4667ed commit 0cf1501
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 14 deletions.
48 changes: 48 additions & 0 deletions Jint.Tests/Runtime/InteropTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3283,5 +3283,53 @@ public void AccessingBaseTypeShouldBeEqualToAccessingDerivedType()

Assert.True(res.AsBoolean());
}

public interface IIndexer<out T>
{
T this[int index] { get; }
}

public interface ICountable<out T>
{
int Count { get; }
}

public interface IStringCollection : IIndexer<string>, ICountable<string>
{
string this[string name] { get; }
}

public class Strings : IStringCollection
{
private readonly string[] _strings;
public Strings(string[] strings)
{
_strings = strings;
}
public string this[string name]
{
get
{
return int.TryParse(name, out var index) ? _strings[index] : _strings.FirstOrDefault(x => x.Contains(name));
}
}

public string this[int index] => _strings[index];
public int Count => _strings.Length;
}

public class Utils
{
public IStringCollection GetStrings() => new Strings(new [] { "a", "b", "c" });
}

[Fact]
public void AccessingInterfaceShouldContainExtendedInterfaces()
{
var engine = new Engine();
engine.SetValue("Utils", new Utils());
var result = engine.Evaluate("const strings = Utils.GetStrings(); strings.Count;").AsNumber();
Assert.Equal(3, result);
}
}
}
49 changes: 35 additions & 14 deletions Jint/Runtime/Interop/TypeResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,29 +212,50 @@ internal bool TryFindMemberAccessor(
PropertyInfo? property = null;
var memberNameComparer = MemberNameComparer;
var typeResolverMemberNameCreator = MemberNameCreator;
foreach (var p in type.GetProperties(bindingFlags))

PropertyInfo? GetProperty(Type t)
{
if (!Filter(engine, p))
foreach (var p in t.GetProperties(bindingFlags))
{
continue;
}
if (!Filter(engine, p))
{
continue;
}

// only if it's not an indexer, we can do case-ignoring matches
var isStandardIndexer = p.GetIndexParameters().Length == 1 && p.Name == "Item";
if (!isStandardIndexer)
{
foreach (var name in typeResolverMemberNameCreator(p))
// only if it's not an indexer, we can do case-ignoring matches
var isStandardIndexer = p.GetIndexParameters().Length == 1 && p.Name == "Item";
if (!isStandardIndexer)
{
if (memberNameComparer.Equals(name, memberName))
foreach (var name in typeResolverMemberNameCreator(p))
{
property = p;
break;
if (memberNameComparer.Equals(name, memberName))
{
property = p;
break;
}
}
}
}

return property;
}

property = GetProperty(type);

if (property is null && type.IsInterface)
{
// check inherited interfaces
foreach (var iface in type.GetInterfaces())
{
property = GetProperty(iface);
if (property is not null)
{
break;
}
}
}

if (property != null)
if (property is not null)
{
accessor = new PropertyAccessor(memberName, property, indexerToTry);
return true;
Expand All @@ -259,7 +280,7 @@ internal bool TryFindMemberAccessor(
}
}

if (field != null)
if (field is not null)
{
accessor = new FieldAccessor(field, memberName, indexerToTry);
return true;
Expand Down

0 comments on commit 0cf1501

Please sign in to comment.