1
Vote

JS Array argument for CLR function

description

namespace JintTest
{
static class Program
{
    [STAThread]
    static void Main()
    {
        JintEngine je = new JintEngine();
        try
        {
            je.Run("
                         var test = new JintTest.Test();
                         var a = [1,2,3];
                         test.CopyO(a);
                         test.Copy(a);
                        ");
        }
        catch (JintException e)
        {
            MessageBox.Show(e.Message);
        }
    }
}

public class Test
{
    public void Copy(int[] a)
    {
    }

    public void CopyO(object a)
    {
    }
}

}

I can not call the Сopy. No matching overload found Сopy. With CopyO all right.
What's wrong?

comments

cin wrote May 25, 2012 at 10:38 PM

js arrays actually aren't so, they are just objects, therefore when overload is resolved it is assumed that the array is just an object.
There is another problem when dealing with js and clr arrays, imagine you have two overloads Copy(int[] a) and Copy(string[] a) which one should be chosen?

Salia2 wrote May 26, 2012 at 5:28 PM

In my opinion, something is wrong with the function "MarshalJsValue" (Marchal.cs).

m_arrayMarshllers[typeof(T)] = marshller = Delegate.CreateDelegate(
                            typeof(Func<JsObject, T>),
                            this,
                            typeof(Marshaller)
                                .GetMethod("MarshalJsFunctionHelper")
                                .MakeGenericMethod(typeof(T).GetElementType())
                        );
1) GetMethod return null, because "MarshalJsFunctionHelper" is close function.
2) "MarshalJsFunctionHelper" is no generic. May be "MarshalJsArrayHelper".

I try next code (and open method "MarshalJsArrayHelper")

m_arrayMarshllers[typeof(T)] = marshller = Delegate.CreateDelegate(
                            typeof(Jint.Delegates.Func<JsObject, T>), 
                            this,
                            typeof(Marshaller)
                            .GetMethod("MarshalJsArrayHelper")
                            .MakeGenericMethod(typeof(T).GetElementType()));
In this case next test pass.
...
string script = @"var a = [1,2, 4]; TestMethod(a); ";
        new JintEngine()
        .SetFunction("TestMethod", new Action<int[]>(TestMethod))
        .Run(script);
...

public void TestMethod(int[] b) { }

cin wrote May 28, 2012 at 10:02 PM

Looks like you are right, but there is something unclear in this issue... Exception you pointed in your first post is specific to overloaded methods only. I guess, there should be InvalidOperationException thrown by MakeGenericMethod in this case.

Salia2 wrote May 29, 2012 at 5:06 AM

It throws an "Object reference not set to an instance of an object. Line: 5 Char: 0
No source code available."

Exeption from my first post from other program with a similar problem (Class with a function that takes an array as an argument. But there is an overload function Copy (int[] a) and Copy (int a))

Salia2 wrote May 29, 2012 at 5:08 AM

I add function (void Copy(int a)) in class Test.
Now exeption is "No matching overload found Copy<>
Line: 5 Char: 0
No source code available."

cin wrote May 29, 2012 at 9:07 PM

now it's clear:
  1. The first exception you get "No matching overload found" is a feature
  2. The second exception you get while calling a not overloaded method is a bug which you mentioned to me, and I will fix it.

Salia2 wrote Jun 1, 2012 at 11:44 AM

That is no support for overloaded CLR functions?

cin wrote Jun 1, 2012 at 7:13 PM

CLR overloads are supported but with some limitations, for example js-arrays are not recognized as CLR arrays.
The main problem of usage overloads from a script is to correctly determine a method signature, this leads to some side effects:
  1. You need to determine a signature at runtime
  2. When using a native js objects you can't exactly map them to a corresponding CLR type, for example numbers
    Therefore overloads causes a performance penalties and sometimes they doesn't work as you expect.
When you are using a regular CLR method (without overloads) Jint will try to coerce parameters from script to be compatible with arguments of the method