Creating a scope and calling functions in that scope

Nov 13, 2009 at 1:20 AM

The way I use Rhino in ObjectCloud is that I create a scope, load a bunch of Javascript into it, and then programmatically call functions from C# that are created in the scope.

In essence, if my Javascript defines "function A() {}", I will obtain Rhino's version of a JsFunction object for the A function, and then programmatically call Rhino's equivalent of the JsFunction.Execute() method from C#.

I can't seem to figure out how to do this with Jint.  Below is a test program where I try to do this.  The first call to jintEngine.Run loads the scope, but returns null.  While I can prove that I can call into A and B within the context of a jintEngine.Run() call; none of my attempts to get a function that I can call work.

Any idea of what to do?


using System;
using System.Collections.Generic;
using System.Text;

using Jint;
using Jint.Native;

namespace Get_Jint_Function
{
    class Program
    {
        static void Main(string[] args)
        {
            string javascriptFunctions = @"
function A(a)
{
   return a + 1;
}

function B(b)
{
   return b - 1;
}
";
            JintEngine jintEngine = new JintEngine();

            object result = jintEngine.Run(javascriptFunctions);

            //JsFunction A = ???
            //JsFunction B = ???

            object a;
            try
            {
                // This returns {undefined}
                a = jintEngine.Run("return A;");
            }
            catch { }

            // b returns as a double
            object b = jintEngine.Run("return B(22);");

            // This returns {undefined}
            object func = jintEngine.Run("return function(){};");

            jintEngine.SetFunction("Pusher", new MyAction(NoOp));

            // These throw exceptions because they never expose the JS* types
            jintEngine.Run("Pusher(22.3); return 0;");
            jintEngine.Run("Pusher(B); return 0;");
            jintEngine.Run("Pusher(this); return 0;");
        }

        public static void NoOp(JsInstance arg)
        {
        }
    }

    public delegate void MyAction(JsInstance arg);
}

 

Nov 16, 2009 at 2:18 AM

I have the exact same problem! If someone knows any way to do that I'll be more grateful!

Nov 16, 2009 at 5:24 AM

So if you dig into Jint's source code a little bit, the last line of Run() removes the Js... wrapper.  A RunUnrapped() could return the Js... object for further control from C#.

That still doesn't solve the callback problem.  I'd like to pass a Javascript function to a C# function, and then have the C# function call the Javascript function.

For example, in the first line of http://objectcloud.kicks-ass.net/Classes/posts, I call the "elevate" function, which is implemented in C# and runs the Javascript callback under an elevated security context.  A few lines down, lockMe is a C# function that takes a Javascript callback and provides a locking mechanism.

This works very well with Rhino and IKVM, but unfortunately Jint is unable to pass the JsFunction object to the callback.  When you run the sample code that I posted above, trying to pass a Javascript function to C# causes an exception.

 

Coordinator
Nov 16, 2009 at 7:03 AM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.