Calling JavaScript Functions in Jint 2.0

Mar 4, 2014 at 3:07 AM
Hello,

I am having trouble figuring out how to call a JavaScript function (multiple times without recompilation) from a script via the Jint.Engine object.

Before 2.0, I was using the JintEngine to pre-compile a javascript with a global function, like:

SomeFile.js:
function OnProcessProject(P)
{
 // perform javascript actions on P
}
.cs File:
private JintEngine m_Script;
Constructor()
{
  m_Script = new JintEngine();
  m_Script.Run( File.ReadAllText("..\SomeFile.js") );
}

...

public void ProcessProjects(List<Project> projectList)
{
  foreach (var project in projectList)
  {
    m_Script.Call("OnProcessProject", new object[] { project });
  }
}
Now, I can't find a "call" function anywhere unless I get crazy with the debugger and try to extract the function object for OnProcessProject() from the global environment, at which point I discovered a Call() function which is confusing (e.g. impossible) to use (creating JsNative objects for parameters wasn't working). I tried a work around using Jint.Engine.Execute() ...

.cs File:
private Jint.Engine m_Script;
Constructor()
{
  m_Script = new Jint.Engine();
  m_Script.Execute(File.ReadAllText("..\SomeFile.js"));
}
...
public void ProcessProjects(List<Project> projectList)
{
  foreach (var project in projectList)
  {
    m_Script.SetValue("__jint_project", project);
    m_Script.Execute("OnProcessProject(__jint_project);");
  }
}
... unfortunately, after the first project I get an exception for an existing key (e.g. "__jint_project"), meaning this tactic only works for one Project object then fails forever after.

Is there an easier API for calling a global or namespaced function via the C# end with parameters included?


Thanks!
Mar 4, 2014 at 3:36 AM
Found the solution on git hub page and some playing around with auto complete:
var function = engine.GetGlobalValue("OnProcessObject").ToObject() as Delegate;
foreach (var project in projectList)
{
  var result = function.DynamicInvoke(
    new JsValue("null") // Fake "this" pointer since function is not called in an object.
    new JsValue[] { Jint.Native.JsValue.FromObject(project) } // Param list: Convert the object to a JsValue type.
  );
}
Sorry for the bother.
Mar 4, 2014 at 5:32 AM
I am also thinking of providing a helper method to call directly a js function result with clr parameters, and the conversion to JsValue would be done automatically. some think like :
engine.Invoke("OnProcessObject", project)
And if a this value is necessary it would be
engine.Invoke(thisValue, "OnProcessObject", project)
This could be replicated with JsValue values directly too. I assume calling a js function from the clr is a common usage.
Mar 4, 2014 at 6:53 AM
You don't even have to wait for it, just pushed it. Look at the readme to see how to use it.
Jan 2, 2015 at 12:38 PM
Edited Jan 2, 2015 at 12:42 PM
I have a slightly different problem:

Java script:
 function Panel(somevar)
 {
      this.objectBehind= somevar;
 }
 Panel.prototype.objectBehind;

Panel.prototype.OnButton1Pushed =
function ()
{
    this.objectBehind.Led1 = 1;
};
Then I want to create a Javascript Panel object, by calling the ctor, and set the this.objectBehind.

How do I do that?
By the way, my jint 2.4.0 does not have the Engine.GetGlobalValue method?

Another problem I have, is that setting the objectBehind with a c# object seems to work, but then accessing it from javascript fails.

.cs code:
         engine.Execute("var myPanel = new Panel()");
        JsValue blockAsScript = engine.GetValue("myPanel");
        Block block = new Block();//object behined
        engine.SetValue(myPanel.objectBehind", block);//set it

        engine.Execute("myPanel.OnButton1Pushed();");//fails
alternative works:
        engine.SetValue("block", block);//first register the c# object as known var "block"
        engine.Execute("myPanel.objectBehind = block;");//assign block to new object myPanel
         engine.Execute("myPanel.OnButton1Pushed();");//ok now
What do I do wrong here?
Is there an explicit API to create java script objects, other then Engine.Excecute?

Or do I need to do it like this?
 JsValue newObject = engine.Execute("new Panel()").GetCompletionValue();