Skip to content

Commit

Permalink
Fix overloaded constructor selection under interop
Browse files Browse the repository at this point in the history
* should not convert to optional parameters when argument count doesn't allow it
  • Loading branch information
lahma committed Apr 29, 2023
1 parent 8b0da8a commit 6c63e02
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 48 deletions.
45 changes: 0 additions & 45 deletions Jint.Tests/Runtime/ConstructorSignature.cs

This file was deleted.

69 changes: 69 additions & 0 deletions Jint.Tests/Runtime/ConstructorSignatureTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System.Globalization;
using Jint.Runtime.Interop;

namespace Jint.Tests.Runtime;

public class ConstructorSignature
{
[Fact]
public void OptionalConstructorParametersShouldBeSupported()
{
var engine = new Engine();

engine.SetValue("A", TypeReference.CreateTypeReference(engine, typeof(A)));

// ParamArray tests
Assert.Equal("3", engine.Evaluate("new A(1, 2).Result").AsString());
Assert.Equal("3", engine.Evaluate("new A(1, 2, null).Result").AsString());
Assert.Equal("3", engine.Evaluate("new A(1, 2, undefined).Result").AsString());
Assert.Equal("5", engine.Evaluate("new A(1, 2, null, undefined).Result").AsString());
Assert.Equal("9", engine.Evaluate("new A(1, 2, ...'packed').Result").AsString());
Assert.Equal("3", engine.Evaluate("new A(1, 2, []).Result").AsString());
Assert.Equal("7", engine.Evaluate("new A(1, 2, [...'abcd']).Result").AsString());

// Optional parameter tests
Assert.Equal("3", engine.Evaluate("new A(1, 2).Result").AsString());
Assert.Equal("6", engine.Evaluate("new A(1).Result").AsString());
Assert.Equal("7", engine.Evaluate("new A(2, undefined).Result").AsString());
Assert.Equal("8", engine.Evaluate("new A(3, undefined).Result").AsString());
Assert.Equal("ab", engine.Evaluate("new A('a').Result").AsString());
Assert.Equal("ab", engine.Evaluate("new A('a', undefined).Result").AsString());
Assert.Equal("ac", engine.Evaluate("new A('a', 'c').Result").AsString());
Assert.Equal("adc", engine.Evaluate("new A('a', 'd', undefined).Result").AsString());
Assert.Equal("ade", engine.Evaluate("new A('a', 'd', 'e').Result").AsString());
}

[Fact]
public void CorrectOverloadShouldBeSelected()
{
var engine = new Engine();
engine.SetValue("B", typeof(B));

Assert.Equal("A-30", engine.Evaluate("new B('A', 30).Result"));
}

private class A
{
public A(int param1, int param2 = 5) => Result = (param1 + param2).ToString();
public A(string param1, string param2 = "b") => Result = string.Concat(param1, param2);
public A(string param1, string param2 = "b", string param3 = "c") => Result = string.Concat(param1, param2, param3);
public A(int param1, int param2, params object[] param3) => Result = (param1 + param2 + param3?.Length).ToString();

public string Result { get; }
}

private class B
{
public B(string param1, float param2, string param3)
{
Result = string.Join("-", param1, param2.ToString(CultureInfo.InvariantCulture), param3);
}

public B(string param1, float param2)
{
Result = string.Join("-", param1, param2.ToString(CultureInfo.InvariantCulture));
}

public string Result { get;}
}
}
18 changes: 15 additions & 3 deletions Jint/Runtime/Interop/TypeReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,26 @@ static ObjectInstance ObjectCreator(Engine engine, Realm realm, ObjectCreateStat
return newArguments;
}
// TODO: edge case, last parameter is ParamArray with optional parameter before?
else if (isParamArray && arguments.Length < parameters.Length - 1)
if (isParamArray && arguments.Length < parameters.Length - 1)
{
return arguments;
}
// optional parameters
else if (parameters.Length >= arguments.Length)
if (parameters.Length >= arguments.Length)
{
// all missing ones must be optional
foreach (var parameter in parameters.AsSpan(parameters.Length - arguments.Length + 1))
{
if (!parameter.IsOptional)
{
// use original arguments
return arguments;
}
}
Array.Copy(arguments, 0, newArguments, 0, arguments.Length);
for (var i = parameters.Length - 1; i >= 0; i--)
Expand All @@ -146,7 +158,7 @@ static ObjectInstance ObjectCreator(Engine engine, Realm realm, ObjectCreateStat
if (arguments.Length - 1 < i || arguments[i].IsUndefined())
{
newArguments[i] = JsValue.FromObject(engine, currentParameter.DefaultValue);
newArguments[i] = FromObject(engine, currentParameter.DefaultValue);
}
}
}
Expand Down

0 comments on commit 6c63e02

Please sign in to comment.