Passing clr object as parameter to js function

Jan 12, 2014 at 8:00 PM
Hello, James. I have read discussions here about passing .Net objects to V8 engine, but i can't just pass my C# objects to existing javascript function. I've tried different approaches, but none works.

Assume that have a function and a handle for it:
var engine = new V8Engine();
var funcHandle = engine.Execute("(function(obj){return obj.Value*2;})");
I have a POCO class like this:
    public class SimpleClass
    {
        public int Value { get; set; }
    }
and i have an instance of this class, so i want to call my function with a parameter of my instance, and then get a result.
How can i do it?

I have tried something like this:
            var funcObj = engine.GetObject(funcHandle);

            var myObj = new SimpleClass() {Value = 123};

            var typebinder =  engine.RegisterType(typeof (SimpleClass), null, false, ScriptMemberSecurity.Locked);
            var v8obj = typebinder.CreateObject(myObj);            
            var result = funcObj.Call(v8obj);
Now the 'result' variable is empty and i have an error printed at console window:
Uncaught TypeError: Cannot read property 'Value' of undefined.
However in debug mode i can see the properties of v8obj and i think it has a value.

Sorry for my poor english and thanks for your help.
Coordinator
Jan 13, 2014 at 6:56 PM
Edited Jan 13, 2014 at 6:58 PM
Part of your problem is this line:
var funcObj = engine.GetObject(funcHandle);
You are using "var ...", so it is taking the type returned ... which is a V8NativeObject object, not a V8Function object. (side note: I should detect and return the correct derived type though, so I'll fix this now). Calling "Call()" on a V8NativeObject is the same as calling it on the handle. Anyhow, the issue remains, you have to look at the parameters of the "Call()" method. It's not the same between the handles and the V8Function object. It's likely you are passing the "this" value only, and the parameter is undefined because you haven't actually passed one in. :)

Try this:
        var funcObj = engine.GetObject<V8Function>(funcHandle); // <--- V8Function
        var myObj = new SimpleClass() {Value = 123};
        var typebinder =  engine.RegisterType(typeof (SimpleClass), null, false, ScriptMemberSecurity.Locked);
        var v8obj = typebinder.CreateObject(myObj);            
        var result = funcObj.Call(null, v8obj); // <--- (null, v8obj)
Hope that helps,
James
Jan 15, 2014 at 4:46 PM
That's work, thanks!
Now I have another problem - if my object has a collection of child objects inside, all of objects in this collection will be undefined - is it not implemented yet, or i need to do something to define these objects?

Also, i'm interested in performance of passing objects. I have noticed, that if i serialize my object to JSON and call this function like a string with serialized object converted to string, it will be faster. So what is the fastest way to do it?
Coordinator
Jan 15, 2014 at 5:13 PM
CLR arrays (i.e. List<SomeObject>) will not (and never) be converted to a simplistic JavaScript array. Why? Because List<> is not just an array, but an object with methods that contains items. When binding CLR objects, you will have access items using the methods on the list/collection object. From JavaScript, Lists and Collections are just child objects like any other.

V8 does, however, support intercepting index requests (i.e. [#]), so I do support that on array objects. Open the test console and you can even try this:
a = new ArratList();
a.Add("test1");
a.Add("test2");
a.Add("test3");
""+a // (will only show "[object Object]"

a2 = a.ToArray();
""+a2   // (will produce the output "test1,test2,test3"
a[0] // (test1)
a2[2] // (test3)
Optionally, if you have access to modify the class, you can always create a method to convert your items and return a V8 specific array using "{V8Engine}.CreateValue(IEnumerable enumerable), or {V8Engine}.CreateArray()". As well, you can create your own indexer for your class (i.e. "public TItem this[int i] {...})."

Hope that helps. :)
Jan 15, 2014 at 5:54 PM
And, as i understood, implementing convert method may be the fastest way to create object?
Coordinator
Jan 15, 2014 at 5:56 PM
The fastest way is probably to implement an indexer property on your class.
Jan 15, 2014 at 6:20 PM
I'l try it. Thanks!