Skip to content

Commit c07bae6

Browse files
committed
In JavaScriptEngineSwitcher.Jint was made complete unification of using of the AllowReflection configuration property
1 parent 576dddf commit c07bae6

File tree

4 files changed

+118
-9
lines changed

4 files changed

+118
-9
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using System.Runtime.CompilerServices;
6+
7+
using OriginalTypeResolver = Jint.Runtime.Interop.TypeResolver;
8+
9+
namespace JavaScriptEngineSwitcher.Jint
10+
{
11+
/// <summary>
12+
/// Interop strategies for different values of the <see cref="JintSettings.AllowReflection"/> configuration property
13+
/// </summary>
14+
internal static class CustomTypeResolvers
15+
{
16+
private static readonly PropertyInfo[] _disallowedProperties =
17+
{
18+
typeof(Delegate).GetProperty("Method"),
19+
typeof(Exception).GetProperty("TargetSite")
20+
};
21+
22+
private static readonly MethodInfo[] _disallowedMethods =
23+
{
24+
typeof(object).GetMethod("GetType"),
25+
typeof(Exception).GetMethod("GetType")
26+
};
27+
28+
private static readonly Lazy<OriginalTypeResolver> _allowingReflection = new Lazy<OriginalTypeResolver>(
29+
() => new OriginalTypeResolver() { MemberFilter = _ => true });
30+
31+
private static readonly Lazy<OriginalTypeResolver> _disallowingReflection = new Lazy<OriginalTypeResolver>(
32+
() => new OriginalTypeResolver() { MemberFilter = IsAllowedMember });
33+
34+
/// <summary>
35+
/// Gets a interop strategy that allows the usage of reflection API in the script code
36+
/// </summary>
37+
public static OriginalTypeResolver AllowingReflection => _allowingReflection.Value;
38+
39+
/// <summary>
40+
/// Gets a interop strategy that disallows the usage of reflection API in the script code
41+
/// </summary>
42+
public static OriginalTypeResolver DisallowingReflection => _disallowingReflection.Value;
43+
44+
45+
private static bool IsAllowedMember(MemberInfo member)
46+
{
47+
bool isAllowed = true;
48+
49+
if (member is PropertyInfo)
50+
{
51+
isAllowed = IsAllowedProperty((PropertyInfo)member);
52+
}
53+
else if (member is MethodInfo)
54+
{
55+
isAllowed = IsAllowedMethod((MethodInfo)member);
56+
}
57+
58+
return isAllowed;
59+
}
60+
61+
[MethodImpl((MethodImplOptions)256 /* AggressiveInlining */)]
62+
private static bool IsAllowedProperty(PropertyInfo property)
63+
{
64+
bool isAllowed = !_disallowedProperties.Contains(property, MemberComparer<PropertyInfo>.Instance);
65+
66+
return isAllowed;
67+
}
68+
69+
[MethodImpl((MethodImplOptions)256 /* AggressiveInlining */)]
70+
private static bool IsAllowedMethod(MethodInfo method)
71+
{
72+
bool isAllowed = !_disallowedMethods.Contains(method, MemberComparer<MethodInfo>.Instance);
73+
74+
return isAllowed;
75+
}
76+
77+
78+
private sealed class MemberComparer<T> : EqualityComparer<T>
79+
where T : MemberInfo
80+
{
81+
public static MemberComparer<T> Instance { get; } = new MemberComparer<T>();
82+
83+
84+
private MemberComparer()
85+
{ }
86+
87+
88+
#region MemberComparer overrides
89+
90+
public override bool Equals(T x, T y)
91+
{
92+
return x.Module == y.Module && x.MetadataToken == y.MetadataToken;
93+
}
94+
95+
public override int GetHashCode(T obj)
96+
{
97+
return obj != null ? obj.GetHashCode() : 0;
98+
}
99+
100+
#endregion
101+
}
102+
}
103+
}

src/JavaScriptEngineSwitcher.Jint/JintJsEngine.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public JintJsEngine(JintSettings settings)
119119
try
120120
{
121121
_jsEngine = new OriginalEngine(options => {
122-
options.Interop.AllowGetType = jintSettings.AllowReflection;
122+
options.Interop.AllowGetType = true;
123123
options.Interop.AllowSystemReflection = true;
124124

125125
options
@@ -142,6 +142,8 @@ public JintJsEngine(JintSettings settings)
142142
}
143143

144144
options.AddObjectConverter(new UndefinedConverter());
145+
options.SetTypeResolver(jintSettings.AllowReflection ?
146+
CustomTypeResolvers.AllowingReflection : CustomTypeResolvers.DisallowingReflection);
145147
});
146148
_cancellationConstraint = _jsEngine.FindConstraint<OriginalCancellationConstraint>();
147149
if (_debuggerBreakCallback != null)

src/JavaScriptEngineSwitcher.Jint/JintSettings.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ public sealed class JintSettings
1313
/// Gets or sets a flag for whether to allow the usage of reflection API in the script code
1414
/// </summary>
1515
/// <remarks>
16-
/// This affects <see cref="Object.GetType"/> and <see cref="Exception.GetType"/>.
16+
/// This affects <see cref="Object.GetType"/>, <c>Exception.GetType</c>,
17+
/// <c>Exception.TargetSite</c> and <c>Delegate.Method</c>.
1718
/// </remarks>
1819
public bool AllowReflection
1920
{

test/JavaScriptEngineSwitcher.Tests/Jint/InteropTests.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,11 @@ string TestAllowReflectionSetting(bool allowReflection)
426426

427427
// Act and Assert
428428
Assert.Null(TestAllowReflectionSetting(true));
429+
#if NET471
429430
Assert.Null(TestAllowReflectionSetting(false));
431+
#else
432+
Assert.Equal("undefined", TestAllowReflectionSetting(false));
433+
#endif
430434
}
431435

432436
[Fact]
@@ -446,10 +450,14 @@ string TestAllowReflectionSetting(bool allowReflection)
446450

447451
// Act and Assert
448452
Assert.Equal(typeof(LoginFailedException).FullName, TestAllowReflectionSetting(true));
453+
#if NET471
454+
Assert.Equal(typeof(LoginFailedException).FullName, TestAllowReflectionSetting(false));
455+
#else
449456

450457
var exception = Assert.Throws<JsRuntimeException>(() => TestAllowReflectionSetting(false));
451458
Assert.Equal("Runtime error", exception.Category);
452459
Assert.Equal("Property 'GetType' of object is not a function", exception.Description);
460+
#endif
453461
}
454462

455463
#endregion
@@ -474,13 +482,8 @@ string TestAllowReflectionSetting(bool allowReflection)
474482
}
475483

476484
// Act and Assert
477-
var exception1 = Assert.Throws<JsRuntimeException>(() => TestAllowReflectionSetting(false));
478-
Assert.Equal("Runtime error", exception1.Category);
479-
Assert.Equal("Property 'GetType' of object is not a function", exception1.Description);
480-
481-
var exception2 = Assert.Throws<JsRuntimeException>(() => TestAllowReflectionSetting(false));
482-
Assert.Equal("Runtime error", exception2.Category);
483-
Assert.Equal("Property 'GetType' of object is not a function", exception2.Description);
485+
Assert.Equal(dateTimeTypeName, TestAllowReflectionSetting(true));
486+
Assert.Equal(dateTimeTypeName, TestAllowReflectionSetting(false));
484487
}
485488

486489
[Fact]

0 commit comments

Comments
 (0)