Creating a JsNumber on C# side to use on the JS side

Jul 25, 2011 at 12:25 AM

 

I'm setting up a C# function to call from a JS script which returns a double.   Then, on the JS side, I assign that value to variable and then try to call toFixed() on that number.   I'm getting an exception:

throw new JsException(Global.ErrorClass.New("Function expected."));

which is in the ExecutionVisitor.cs file  (method is "public void Visit(MethodCall methodCall)").

What I was originally doing was not even using JsNumber on the C# side.  Instead, I used "double" and hoped that some kind of marshaling was going on under the covers to auto-magically convert what the C# side to a JsNumber on the Javascript side.    Then, I started playing with JsNumber directly and this isn't working either.

The JS code is (the print() will work if I use "num" instead of "num.toFixed(2), whether I use a double or JsNumber to represent the C# double value being retrieved and then passed on to the script":

function main()
{
  var num = getDouble();
  print("double = " + num.toFixed(2));
}

The C# code is:

public void InitializeJS()
{
  // print(s) is just outputting the string to a TextBox on a Windows Form

  jint = new JintEngine().
     .SetFunction("print", new Action<string>(s => print(s); }))
     .SetFunction("getDouble", new Func<JsNumber>(() => { return GetDouble(); }))
     .DisableSecurity();

  var source = File.ReadAllText("file.js");
  program = JintEngine.Compile(source, false);
  jint.Run(program);
}

// Num below is of type decimal and is a property type which is
// grabbing a real-time stream of values coming into the C# program
private JsNumber GetDouble()
{
  return new JsNumber(Convert.ToDouble(Num), JsUndefined.Instance);
}
// Here's the Javascript main function getting called repeatedly from the C# side as a new double comes in
public void ValueReceived(double num)
{
  Num = num;
  jint.CallFunction("main", new object[] {});
}

Questions:
1. Is the marshaling supposed to happen where any double I pass to a Javascript gets converted to a JsNumber so my use of JsNumber above is not necessary?
2. Is this a bug and both methods (using double or JsNumber) should have worked with the ".toFixed(2)" function of the Number object being called as a result?  

[note: any syntax errors above are incidental and a result of bad transcribing on my part]
Jul 26, 2011 at 2:18 AM

I've taken a fresh look at this problem and I still don't see the error in what I'm trying to do.    If I wrap a C# double as a JsNumber and pass it back to the Javascript side, call num.toFixed(2) on that wrapped double, then I should have no problem getting the expected result.

Need a little help here.  This isn't rocket science, but I think it's a little silly to have to spend hours figuring out what's going on with something so mundane as this.   I shouldn't have to learn how to be some Jint internals guru to do basic runtime tasks like this.

Developer
Jul 26, 2011 at 7:45 PM

The number you have constructed doesn't have a prototype. You need to specify a correct prototype or just use JintEngine.Global.NumberClass.New method which will do right things for you. Note: a prototype is a dynamic (can be modified) object also which lives in the runtime and therefore you can't create a new "correct" object knowing nothing about runtime (actually, about the global object).

Developer
Jul 26, 2011 at 8:02 PM

Constructing the js object isn't necessarily, it will be marshaled automatically, but the resulting object will be a "compatible" number. All CLR numerical types when marshaled are derived from Number class, therefore marshaled numbers you may consider as simple Numbers or as CLR objects and call methods of both.

If you pass a js object to the script runtime - no marshaling will occur (and may be it will be faster).

Jul 31, 2011 at 3:53 PM

cin,

Hmm, this was my original code and I got that same JsException exception from above when the ".toFixed(2)" function was invoked on the C# double marshaled to the Javascript side.

[One of three things is going on here:

1. I munged the small changes to Jint to get it to compile under .Net 4.0 and this is 100% my fault and the code below works fine under the official Jint binaries.

2. This is a bug in Jint.   I notice that if I had removed the ".toFixed(2)" from the num variable in the Javascript print() function I have, the double on the Javascript side prints out fine.   It's the ".toFixed(2)" call on that double passed over from C# which is raising the JsException.

3. I've assumed a level of seamless integration which doesn't exist and the code below is wrong (strange though, because this works fine under Jurassic).]

Javascript code:

function main()
{
  var num = getDouble();
  print("double = " + num.toFixed(2));
}

C# code:

public void InitializeJS()
{
  // print(s) is just outputting the string to a TextBox on a Windows Form

  jint = new JintEngine().
     .SetFunction("print", new Action<string>(s => print(s); }))
     .SetFunction("getDouble", new Func<double>(() => { return GetDouble(); }))
     .DisableSecurity();

  var source = File.ReadAllText("file.js");
  program = JintEngine.Compile(source, false);
  jint.Run(program);
}

// Num below is of type decimal and is a property type which is
// grabbing a real-time stream of values coming into the C# program
private double GetDouble()
{
  return Num;
}
// Here's the Javascript main function getting called repeatedly from the C# side as a new double comes in
public void ValueReceived(double num)
{
  Num = num;
  jint.CallFunction("main", new object[] {});
}

Developer
Jul 31, 2011 at 10:44 PM

fixed