Tuesday, May 24, 2016

Embed Google V8 JavaScript engine in .Net application

Background

JavaScript is everywhere whether we accept or not. Now a days the trend in new languages is to transpile to JavaScript. That's the way they don't need to worry about runtime. Thanks to fast JavaScript engines such as V8. People are sure once their code is in JavaScript, the engines will run it in the highest speed, even it works in server side with the help if NodeJS technology. For client side desktop development also we can rely on JavaScript using the Electron technology. In all these places JavaScript engines power the execution.

So what about DSLs? Why can't we write our DSL in JavaScript and execute via JavaScript engines? The only constraint here is from our technology / runtime we should be able to send and receive objects to and from JavaScript engine. In simple terms, in our C#.Net application there is a salary calculation which is dynamic and needs to be customizable by user. If we can pass the Employee object to and from JavaScript engine, we can use JavaScript as DSL for our app.

The problem narrows down to
  • Starting JavaScript engine from our technology of choice. Send the JavaScript code to the engine.
  • Passing objects from our application JS engine to manipulate.
Since JS is dynamic and not strictly typed, we can pass any string as program into the engine. Engine will fail the code only during the execution. In this post, we can see how such an interaction can be done between .Net and Chrome V8 JavaScript engine.

Selecting Chrome V8 Engine

There are many implementations out there for Chrome V8 engine. Most of those are compatible directly with native code. From .Net its little difficult to interface with those.

We are going to use one out there named JavaScriptDotNet.

Setting up the environment

Download the binaries from the below repository. They moved the code to Github. But unfortunately the ready made binaries are not there.

http://javascriptdotnet.codeplex.com/

Create our .Net project and refer corresponding binaries. There are .Net 3.5 & 4.0 folders and each folder has 32 and 64 bit versions. Since Chrome is a native unmanaged library and JavaScriptDotNet only provides a managed wrapper over that, we need to be careful in selecting which version. The assembly we need to refer to our .Net project is Noesis.JavaScript.The other dlls should be present in the \bin or running directly of our ,Net application.

How to run JavaScript

Its simple as creating JavaScriptContext and calling Run().

using (JavascriptContext context = new JavascriptContext())
{
    var result = context.Run("3+2");
    MessageBox.Show(result.ToString());
}

How to pass .Net objects to JavaScript and vice versa

Now lets see how can we pass .Net objects into JavaScript. If we can't pass the objects there is no meaning in embedding JavaScript engine inside .Net

Lets take one simple Employee class
public class Employee : INotifyPropertyChanged
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Basic { get; set; }
    public double HRA { get; set; }
}
Employee emp = new Employee() {Basic=100, Name = "Joy" };
Object is also created with one property 'Basic' set to 100. Now lets see what the below code will do on this object.
using (JavascriptContext context = new JavascriptContext())
{
    // Setting the externals parameters to the context
    context.SetParameter("emp", emp, SetParameterOptions.RejectUnknownProperties);
    try
    {
        // Running the script
        context.Run("emp.Total = emp.Basic * 2; emp.HRA = emp.Basic / 2;");
        MessageBox.Show(emp.HRA.ToString());
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error");
    }
}

It will show 50 as the emp.HRA is calculated when JavaScript engine run. Yes now we have embedded JavaScript engine in .Net and JavaScript can now be used as DSL in our C# application.

http://stackoverflow.com/questions/172753/embedding-javascript-engine-into-net

No comments: