Skip to content

Commit 44a0ce0

Browse files
authored
Improve interop conversion logic between numeric types (#1995)
1 parent d30fe18 commit 44a0ce0

File tree

2 files changed

+72
-6
lines changed

2 files changed

+72
-6
lines changed

Jint.Tests/Runtime/InteropTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3698,4 +3698,24 @@ private class MyClass
36983698
{
36993699
public static JsNumber MAX_SAFE_INTEGER = new JsNumber(NumberConstructor.MaxSafeInteger);
37003700
}
3701+
3702+
[Fact]
3703+
public void ShouldFindShortOverload()
3704+
{
3705+
_engine.SetValue("target", new ShortOverloadWithBoolean());
3706+
_engine.Evaluate("target.method(42)").AsString().Should().Be("short");
3707+
}
3708+
3709+
private class ShortOverloadWithBoolean
3710+
{
3711+
public string Method(short s, bool b = true)
3712+
{
3713+
return "short";
3714+
}
3715+
3716+
public string Method(bool b)
3717+
{
3718+
return "boolean";
3719+
}
3720+
}
37013721
}

Jint/Runtime/Interop/InteropHelper.cs

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Diagnostics.CodeAnalysis;
22
using System.Globalization;
33
using System.Reflection;
4+
using System.Runtime.CompilerServices;
45
using Jint.Extensions;
56
using Jint.Native;
67

@@ -120,14 +121,59 @@ private static int CalculateMethodParameterScore(Engine engine, ParameterInfo pa
120121
return 5;
121122
}
122123

123-
if (paramType == typeof(int) && parameterValue.IsInteger())
124+
const int ScoreForDifferentTypeButFittingNumberRange = 2;
125+
if (parameterValue.IsNumber())
124126
{
125-
return 0;
126-
}
127+
var num = (JsNumber) parameterValue;
128+
var numValue = num._value;
127129

128-
if (paramType == typeof(float) && objectValueType == typeof(double))
129-
{
130-
return parameterValue.IsInteger() ? 1 : 2;
130+
if (paramType == typeof(double))
131+
{
132+
return 0;
133+
}
134+
135+
if (paramType == typeof(float) && numValue is <= float.MaxValue and >= float.MinValue)
136+
{
137+
return ScoreForDifferentTypeButFittingNumberRange;
138+
}
139+
140+
var isInteger = num.IsInteger() || TypeConverter.IsIntegralNumber(num._value);
141+
142+
// if value is integral number and within allowed range for the parameter type, we consider this perfect match
143+
if (isInteger)
144+
{
145+
if (paramType == typeof(int))
146+
{
147+
return 0;
148+
}
149+
150+
if (paramType == typeof(long))
151+
{
152+
return ScoreForDifferentTypeButFittingNumberRange;
153+
}
154+
155+
// check if we can narrow without exception throwing versions (CanChangeType)
156+
var integerValue = (int) num._value;
157+
if (paramType == typeof(short) && integerValue is <= short.MaxValue and >= short.MinValue)
158+
{
159+
return ScoreForDifferentTypeButFittingNumberRange;
160+
}
161+
162+
if (paramType == typeof(ushort) && integerValue is <= ushort.MaxValue and >= ushort.MinValue)
163+
{
164+
return ScoreForDifferentTypeButFittingNumberRange;
165+
}
166+
167+
if (paramType == typeof(byte) && integerValue is <= byte.MaxValue and >= byte.MinValue)
168+
{
169+
return ScoreForDifferentTypeButFittingNumberRange;
170+
}
171+
172+
if (paramType == typeof(sbyte) && integerValue is <= sbyte.MaxValue and >= sbyte.MinValue)
173+
{
174+
return ScoreForDifferentTypeButFittingNumberRange;
175+
}
176+
}
131177
}
132178

133179
if (paramType.IsEnum &&

0 commit comments

Comments
 (0)