Using JavaScript Frameworks inside C# with ChakraBridge

This article is part of a web development series from Microsoft. Thank you for supporting the partners who make SitePoint possible.

JavaScript has, without doubt, the most vibrant ecosystem out there. There are gazillions of new frameworks released every month (https://www.javascripting.com/).

As a C# developer – even with a great, active C# community – you may sometimes find yourself a little bit jealous.

What if we could bring the JavaScript language and ecosystem also into the C# world? What if a C# developer could use JavaScript inside C#?

Fret not! I’m thrilled to announce a new WinRT project I’ve created – ChakraBridge – which will allow you to get invited to the party like any web developers.

Indeed, thanks to Chakra (the JavaScript engine used by Microsoft Edge), it is now possible to host one of the fastest JavaScript engines (and also the one with the highest support of ECMAScript 6) inside any Universal Windows Platform application. ChakraBridge embeds Chakra engine in a WinRT application and provides all required high level tools to use it seamlessly in a C# / UWP application.

People developing a HTML/JS/CSS based UWP App (WWA or hosted app in the old world) don’t need to host Chakra separately as it’s already a part of the sandbox.

Once you’ve picked the framework that you want to use, you have to inject it into your Chakra context. In my case I wanted to use CDC (CloudDataConnector) because I needed a way to seamlessly connect to various cloud data providers (Amazon, Azure, CouchDB, etc..). You can either download the .js files and embed them in your project or download them every time you launch your application:

Nothing fancy here, I’m just using CDC to connect to an Azure mobile service in order to get a list of people.

Getting data back from JavaScript world

Next, I’ll get my data back from the JavaScript context. As you may have seen in the “sample.js” file, when the data context is updated, I’m calling a global function called sendToHost. This function is provided by ChakraBridge to allow you to communicate with the C# host.

To get it working, you have to define what types can be sent from JavaScript:

CommunicationManager.RegisterType(typeof(People[]));

So now when sendToHost is called from JavaScript context, a specific event will be raised on C# side:

The current version of ChakraBridge accepts int, double, bool and string types.

Debugging in the JavaScript context

Thanks to Visual Studio, it is still possible to debug your JavaScript code even if you are now in a C# application. To do so, you first have to enable script debugging in the project properties:

Then, you can set a breakpoint in your JavaScript code.

But there is a trick to know: You cannot set this breakpoint in the files in your project as they are here just as a source. You have to reach the executed code through the Script Documents part of the Solution Explorer when running in debug mode:

How does it work?

Interop

Let’s now discuss how things work under the hood.

Basically, Chakra is based on a Win32 library located at “C:\Windows\System32\Chakra.dll” on every Windows 10 desktop devices.

So the idea here is to provide a internal C# class that will embed all entry points to the DLL through DllImport attributes:

The list of available functions is pretty long. ChakraBridge is here to encapsulate these functions and provide a higher level abstraction.

Other option to consider here: you can also use Rob Paveza’s great wrapper called js-rtwinrt: https://github.com/robpaveza/jsrt-winrt. It’s higher-level than the pure Chakra engine and it avoids needing P/Invoke.

Providing missing pieces

One important point to understand is that Chakra only provides the JavaScript engine. But you, as the host, have to provide tools used alongside JavaScript. These tools are usually provided by browsers (think about C# without .NET).

For instance, XmlHttpRequest object or setTimeout function are not part of JavaScript language. They are tools used BY the JavaScript language in the context of your browser.

To allow you to use JavaScript frameworks, ChakraBridge provides some of these tools.

This is an ongoing process and more tools will be added to ChakraBridge in the future by me or the community.

SetTimeoutJavaScriptNativeFunction is the method that will be projected inside JavaScript context. You can note that every parameter is gathered as a JavaScriptValue and then cast to the expected value. For the callback function (callbackValue), we have to indicate to JavaScript garbage collector that we hold a reference so it could not free this variable even if no one is holding it inside JavaScript context:

Native.JsAddRef(callbackValue, out refCount);

The reference has to be released once the callback is called:

Native.JsRelease(callbackValue, out refCount);

On the other hand, C# garbage collector has no idea of what is happening inside the Chakra black box. So you have to take care of keeping reference to objects or functions that you project into the JavaScript context. In the specific case of setTimeout implementation, you first have to create a static field that point to your C# method just to keep a reference on it.

Why not use a Webview?

This is a valid question that you may ask. Using only Chakra provides some great advantages:

Memory footprint: No need to embed HTML and CSS engines as we already have XAML.

Performance: We can directly control JavaScript context and, for instance, call JavaScript function without having to go through a complex process like with the webview.

Simplicity: The webview needs to navigate to a page to execute JavaScript. There is no straightforward way to just execute JavaScript code.

Control: By providing our own tools (like XHR or setTimeout), we have a high level of granularity to control what JavaScript can do.

Going Further

Thanks to Chakra engine, this is the beginning of a great collaboration between C#, XAML and JavaScript. Depending on the community response, I plan to add more features in the ChakraBridge project to be able to handle more JavaScript frameworks (for instance, it could be great to add support for canvas drawing in order to be able to use all awesome charting frameworks available for JavaScript).

More hands-on with Web Development

This article is part of the web development series from Microsoft tech evangelists on practical JavaScript learning, open source projects, and interoperability best practices including Microsoft Edge browser and the new EdgeHTML rendering engine.

We encourage you to test across browsers and devices including Microsoft Edge – the default browser for Windows 10 – with free tools on dev.modern.IE:

David Catuhe is a Principal Program Manager at Microsoft focusing on web development. He is author of the babylon.js framework for building 3D games with HTML5 and WebGL. Read his blog on MSDN or follow him on Twitter.