Skip to content

Commit eb091eb

Browse files
authored
Tweak object wrapper reported members logic (#1956)
1 parent 2f3a801 commit eb091eb

File tree

5 files changed

+77
-56
lines changed

5 files changed

+77
-56
lines changed

Jint.Tests/Runtime/InteropTests.cs

Lines changed: 64 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3297,9 +3297,13 @@ private class Container
32973297
public BaseClass Get() => _child;
32983298
}
32993299

3300-
private class BaseClass { }
3300+
private class BaseClass
3301+
{
3302+
}
33013303

3302-
private class Child : BaseClass { }
3304+
private class Child : BaseClass
3305+
{
3306+
}
33033307

33043308
[Fact]
33053309
public void AccessingBaseTypeShouldBeEqualToAccessingDerivedType()
@@ -3328,6 +3332,7 @@ public interface IStringCollection : IIndexer<string>, ICountable<string>
33283332
public class Strings : IStringCollection
33293333
{
33303334
private readonly string[] _strings;
3335+
33313336
public Strings(string[] strings)
33323337
{
33333338
_strings = strings;
@@ -3340,7 +3345,7 @@ public Strings(string[] strings)
33403345

33413346
public class Utils
33423347
{
3343-
public IStringCollection GetStrings() => new Strings(new [] { "a", "b", "c" });
3348+
public IStringCollection GetStrings() => new Strings(new[] { "a", "b", "c" });
33443349
}
33453350

33463351
[Fact]
@@ -3384,6 +3389,7 @@ private class MetadataWrapper : IDictionary<string, object>
33843389
public bool ContainsKey(string key) => throw new NotImplementedException();
33853390
public void Add(string key, object value) => throw new NotImplementedException();
33863391
public bool Remove(string key) => throw new NotImplementedException();
3392+
33873393
public bool TryGetValue(string key, out object value)
33883394
{
33893395
value = "from-wrapper";
@@ -3467,6 +3473,7 @@ public void ShouldRespectConcreteGenericReturnTypes()
34673473
});
34683474

34693475
var result = new List<string>();
3476+
34703477
void Debug(object o)
34713478
{
34723479
result.Add($"{o?.GetType().Name ?? "null"}: {o ?? "null"}");
@@ -3487,102 +3494,126 @@ void Debug(object o)
34873494

34883495
private class ClrMembersVisibilityTestClass
34893496
{
3490-
public int A { get; set; } = 10;
3497+
public string Field = "field";
34913498

3492-
public int F()
3499+
public int Property { get; set; } = 10;
3500+
3501+
public int Method()
34933502
{
34943503
return 4;
34953504
}
3505+
3506+
public string Extras { get; set; }
34963507
}
34973508

34983509
[Fact]
3499-
public void ShouldNotSeeClrMethods()
3510+
public void PropertiesShouldNotSeeReportMethodsWhenMemberTypesActive()
35003511
{
35013512
var engine = new Engine(opt =>
35023513
{
35033514
opt.Interop.ObjectWrapperReportedMemberTypes = MemberTypes.Field | MemberTypes.Property;
35043515
});
3505-
3516+
35063517
engine.SetValue("clrInstance", new ClrMembersVisibilityTestClass());
3507-
3508-
var val = engine.GetValue("clrInstance");
35093518

3510-
var obj = val.AsObject();
3511-
var props = obj.GetOwnProperties().Select(x => x.Key.ToString()).ToList();
3512-
3513-
props.Should().BeEquivalentTo(["A"]);
3519+
var val = engine.GetValue("clrInstance");
3520+
3521+
var obj = val.AsObject();
3522+
var props = obj.GetOwnProperties().Select(x => x.Key.ToString()).ToList();
3523+
3524+
props.Should().BeEquivalentTo("Property", "Extras", "Field");
35143525
}
3515-
3526+
35163527
[Fact]
3517-
public void ShouldSeeClrMethods()
3528+
public void PropertyKeysShouldReportMethods()
35183529
{
35193530
var engine = new Engine();
3520-
3531+
3532+
engine.SetValue("clrInstance", new ClrMembersVisibilityTestClass());
3533+
3534+
var val = engine.GetValue("clrInstance");
3535+
var obj = val.AsObject();
3536+
var props = obj.GetOwnProperties().Select(x => x.Key.ToString()).ToList();
3537+
3538+
props.Should().BeEquivalentTo("Property", "Extras", "Field", "Method");
3539+
}
3540+
3541+
[Fact]
3542+
public void PropertyKeysShouldObeyMemberFilter()
3543+
{
3544+
var engine = new Engine(options =>
3545+
{
3546+
options.SetTypeResolver(new TypeResolver
3547+
{
3548+
MemberFilter = member => member.Name == "Extras"
3549+
});
3550+
});
3551+
35213552
engine.SetValue("clrInstance", new ClrMembersVisibilityTestClass());
3522-
3553+
35233554
var val = engine.GetValue("clrInstance");
35243555
var obj = val.AsObject();
35253556
var props = obj.GetOwnProperties().Select(x => x.Key.ToString()).ToList();
35263557

3527-
props.Should().BeEquivalentTo(["A", "F"]);
3558+
props.Should().BeEquivalentTo("Extras");
35283559
}
3529-
3560+
35303561
private class ClrMembersVisibilityTestClass2
35313562
{
35323563
public int Get_A { get; set; } = 5;
35333564
}
3534-
3565+
35353566
[Fact]
35363567
public void ShouldSeeClrMethods2()
35373568
{
35383569
var engine = new Engine();
3539-
3570+
35403571
engine.SetValue("clrInstance", new ClrMembersVisibilityTestClass2());
3541-
3572+
35423573
var val = engine.GetValue("clrInstance");
35433574

35443575
var obj = val.AsObject();
35453576
var props = obj.GetOwnProperties().Select(x => x.Key.ToString()).ToList();
3546-
3547-
props.Should().BeEquivalentTo(["Get_A"]);
3577+
3578+
props.Should().BeEquivalentTo("Get_A");
35483579
}
3549-
3580+
35503581
[Fact]
35513582
public void ShouldNotThrowOnInspectingClrFunction()
35523583
{
35533584
var engine = new Engine();
3554-
3585+
35553586
engine.SetValue("clrDelegate", () => 4);
3556-
3587+
35573588
var val = engine.GetValue("clrDelegate");
35583589

35593590
var fn = val as Function;
35603591
var decl = fn!.FunctionDeclaration;
35613592

35623593
decl.Should().BeNull();
35633594
}
3564-
3595+
35653596
private class ShouldNotThrowOnInspectingClrFunctionTestClass
35663597
{
35673598
public int MyInt()
35683599
{
35693600
return 4;
35703601
}
35713602
}
3572-
3603+
35733604
[Fact]
35743605
public void ShouldNotThrowOnInspectingClrClassFunction()
35753606
{
35763607
var engine = new Engine();
3577-
3608+
35783609
engine.SetValue("clrCls", new ShouldNotThrowOnInspectingClrFunctionTestClass());
3579-
3610+
35803611
var val = engine.GetValue("clrCls");
35813612
var clrFn = val.Get("MyInt");
3582-
3613+
35833614
var fn = clrFn as Function;
35843615
var decl = fn!.FunctionDeclaration;
3585-
3616+
35863617
decl.Should().BeNull();
35873618
}
35883619

@@ -3592,13 +3623,5 @@ public void StringifyShouldIncludeInheritedFieldsAndProperties()
35923623
var engine = new Engine();
35933624
engine.SetValue("c", new Circle(12.34));
35943625
engine.Evaluate("JSON.stringify(c)").ToString().Should().Be("{\"Radius\":12.34,\"Color\":0,\"Id\":123}");
3595-
3596-
3597-
engine = new Engine(options =>
3598-
{
3599-
options.Interop.ObjectWrapperReportOnlyDeclaredMembers = true;
3600-
});
3601-
engine.SetValue("c", new Circle(12.34));
3602-
engine.Evaluate("JSON.stringify(c)").ToString().Should().Be("{\"Radius\":12.34}");
36033626
}
36043627
}

Jint/Native/Atomics/AtomicsInstance.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Numerics;
21
using System.Threading;
32
using Jint.Collections;
43
using Jint.Native.Object;

Jint/Options.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -371,13 +371,6 @@ public class InteropOptions
371371
/// All other values are ignored.
372372
/// </summary>
373373
public MemberTypes ObjectWrapperReportedMemberTypes { get; set; } = MemberTypes.Field | MemberTypes.Property | MemberTypes.Method;
374-
375-
/// <summary>
376-
/// Whether object wrapper should only report members that are declared on the object type itself, not inherited members. Defaults to false.
377-
/// This is different from JS logic where only object's own members are reported and not prototypes.
378-
/// </summary>
379-
/// <remarks>This configuration does not affect methods, only methods declared in type itself will be reported.</remarks>
380-
public bool ObjectWrapperReportOnlyDeclaredMembers { get; set; }
381374
}
382375

383376
public class ConstraintOptions

Jint/Runtime/Interop/ObjectWrapper.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,15 +257,16 @@ private IEnumerable<JsValue> EnumerateOwnPropertyKeys(Types types)
257257

258258
// we take public properties, fields and methods
259259
var bindingFlags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public;
260-
if (interopOptions.ObjectWrapperReportOnlyDeclaredMembers)
261-
{
262-
bindingFlags |= BindingFlags.DeclaredOnly;
263-
}
264260

265261
if ((interopOptions.ObjectWrapperReportedMemberTypes & MemberTypes.Property) == MemberTypes.Property)
266262
{
267263
foreach (var p in ClrType.GetProperties(bindingFlags))
268264
{
265+
if (!interopOptions.TypeResolver.Filter(_engine, ClrType, p))
266+
{
267+
continue;
268+
}
269+
269270
var indexParameters = p.GetIndexParameters();
270271
if (indexParameters.Length == 0)
271272
{
@@ -278,15 +279,21 @@ private IEnumerable<JsValue> EnumerateOwnPropertyKeys(Types types)
278279
{
279280
foreach (var f in ClrType.GetFields(bindingFlags))
280281
{
282+
if (!interopOptions.TypeResolver.Filter(_engine, ClrType, f))
283+
{
284+
continue;
285+
}
286+
281287
yield return JsString.Create(f.Name);
282288
}
283289
}
284290

285291
if ((interopOptions.ObjectWrapperReportedMemberTypes & MemberTypes.Method) == MemberTypes.Method)
286292
{
287-
foreach (var m in ClrType.GetMethods(bindingFlags | BindingFlags.DeclaredOnly))
293+
foreach (var m in ClrType.GetMethods(bindingFlags))
288294
{
289-
if (m.IsSpecialName)
295+
// we won't report anything from base object as it would usually not be something to expect from JS perspective
296+
if (m.DeclaringType == typeof(object) || m.IsSpecialName || !interopOptions.TypeResolver.Filter(_engine, ClrType, m))
290297
{
291298
continue;
292299
}

Jint/Runtime/Interop/Reflection/DynamicObjectAccessor.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Dynamic;
2-
using System.Reflection;
32
using Jint.Native;
43

54
#pragma warning disable IL2092

0 commit comments

Comments
 (0)