Category Archives: Hosting

JsRT: Wrappers for C++

One unfortunate side-effect of the fact that the JsRT API is a flat Win32-style API is that it can be a little… painful to use in C++. Some of the conventions, particularly the use of error code returns everywhere and the use of return parameters, mean that you have to write a lot of boilerplate code. And marshalling values between C++ and JavaScript can be very cumbersome. So with that in mind, I’ve written some sample C++ wrappers that make the process of working with the JsRT APIs a lot nicer in C++.

You can get them from my GitHub account here. For more information, here’s part of the readme, which covers some of the highlights of the wrappers:

A Tour Through the Helpers

Most of the wrappers simply provide a nice object-oriented interface over the JsRT API. For example, creating a runtime and a context works like this:

jsrt::runtime runtime = jsrt::runtime::create();
jsrt::context context = runtime.create_context();

There are, however, a number of special features in the wrappers.

Context scopes

A context scope (jsrt::context::scope) automatically sets the current context when it comes into scope and clears the current context when it goes out of scope. This greatly simplifies working with scopes. For example:

jsrt::runtime runtime = jsrt::runtime::create();
jsrt::context context = runtime.create_context();
{
    jsrt::context::scope scope(context);
    ... work with context ...
}
// Context has automatically been set back to original value.
runtime.dispose();

Pinned references

To keep a reference to a Chakra object alive, it must be visible to the Chakra garbage collector (i.e. on the stack or stored in the garbage collected heap) or it has to be pinned using JsAddRef. The pinned<T> class functions as a smart-pointer template that keeps a reference alive using JsAddRef and JsRelease automatically. For example:

{
    jsrt::pinned<jsrt::object> pinned_obj = jsrt::object::create();
    // Object reference does not have to stay on the stack or in the GC heap
}
// Reference can now be garbage collected

Value translation

Value getter and setter functions can be strongly-typed, allowing automatic marshalling of JavaScript values to C++ values and vice versa. For example:

jsrt::object obj = jsrt::object::create();
obj.set_property(jsrt::property_id::create(L"boolProperty"), true);
bool bool_value = obj.get_property<bool>(jsrt::property_id::create(L"boolProperty"));
obj.set_property(jsrt::property_id::create(L"stringProperty"), L"foo");

The wrappers marshal types in the following way:

  • number values are marshalled to/from double

  • string values are marshalled to/from std::wstring

  • Boolean values are marshalled to/from bool

Strongly-typed arrays

Similarly, arrays can be strongly typed and accessed using numeric indexes:

jsrt::array<double> darray = jsrt::array<double>::create(1);
darray[0] = 10;
darray[1] = 20;

Functions

Perhaps the most useful aspect of the wrappers is the way that JavaScript functions can be wrapped and their arguments and return values marshalled to C++ types, and vice versa. For example:

auto f = (jsrt::function<double, double, double>)jsrt::context::evaluate(
    L"function f(a, b) { return a + b; }; f;");
double a = f(jsrt::context::undefined(), 1, 2);

Native functions can also be wrapped:

double add(const jsrt::call_info &info, double a, double b) { return a + b; }
auto nf = jsrt::function<double, double, double>::create(add);
jsrt::context::global().set_property(jsrt::property_id::create(L"add"), nf);
jsrt::context::run(L"add(1, 2)");

When calling a function wrapper, the first argument to the function call is the this value for the call. Function wrappers can also be bound to a particular value of this. For example:

auto bf = jsrt::bound_function<jsrt::value, double, double, double>::create(
    jsrt::context::undefined(),
    (jsrt::function<double, double, double>)jsrt::context::evaluate(
        L"function f(a, b) { return a + b; }; f;"));
double ba = bf(1, 2);

You should also follow me on Twitter here.

JsRT Sample Bug Fixed

This happened a while ago but just getting to it now because of my blog hiccup. A sharp-eyed reader pointed out a problem with my C# and VB Chakra hosting samples (on MSDN and on GitHub). When passing a host callback from managed code, I forgot to hold on to a managed reference to the delegate I was passing out to Chakra. So if the CLR ran a GC, it would dispose the delegate and then a callback on that delegate would jump into hyperspace. The samples are now correct. Ah, the joys of coordinating GCs.

You should also follow me on Twitter here.

Memory profiling in Visual Studio 2013 with JsRT

One of the cool features of Visual Studio (starting in Visual Studio 2012 Update 1) is its JavaScript memory profiler. The profiler can take snapshots of the JavaScript heap and then gives you a nice UI you can use to drill in to those snapshots and compare them as you like:

Comparing two snapshots

Drilling in to a snapshot

Wouldn’t it be great to be able to utilize this to analyze the JavaScript memory usage in an app that hosts Chakra using JsRT? Well, you can! I’ve uploaded a new sample (and checked it in to my GitHub repo) that allows a JsRT app to generate heap dumps in a way that Visual Studio 2013 will be able to read. It doesn’t look quite as beautiful at the examples above–I didn’t go through the trouble of generating a screenshot for the summary page–but it should be entirely functional.

The sample project builds a C++ DLL that exports five functions:

  • bool InitializeMemoryProfileWriter() initializes the overall profile writer and should be called when you load the DLL.
  • MemoryProfileHandle StartMemoryProfile() starts a specific profile (called a “diagnostic session” in Visual Studio).
  • bool WriteSnapshot(MemoryProfileHandle memoryProfileHandle, IActiveScriptProfilerHeapEnum *enumerator) takes a memory profile handle and a heap enumerator (which can be obtained from JsEnumerateHeap) and writes the actual memory snapshot. Note that you can do this multiple times before finishing the memory profile. Each snapshot is written separately into the diagnostic session.
  • bool EndMemoryProfile(MemoryProfileHandle memoryProfileHandle, const wchar_t *filename) finishes the memory profile and writes it out to a file. The file should have a .diagsession extension if you want it to be natively recognized by VS when you open it. After this call, the memory profile handle is now invalid.
  • void ReleaseMemoryProfileWriter() releases the overall profiler writer and should be called when you’re shutting down or done with all profiling.

One thing to note is that once you’ve called JsEnumerateHeap for a particular JsRT runtime, you won’t be able to do anything in that runtime until the IActiveScriptProfilerHeapEnum pointer has been released.

We’ve already been using this code internally to look at the memory usage of some internal JsRT hosts, and it’s been very helpful! Let me know if there are problems or issues, and feel free to grab me on Twitter if you have any questions.

You should also follow me on Twitter here.

JsRT samples updated for Windows 8.1 RTM

As a few people have noticed, we took a small breaking change to the JsRT API between the Windows 8.1 Preview and Windows 8.1 RTM. The JsCreateFunction API got an additional parameter that allows registering a piece of data (which can just be null) with the native callback which will be provided to the callback when it’s invoked. It’s a super-useful place to stash something like a “this” pointer for a C++ callback, which is why we added it before the concrete completely dried on the API. It does mean, though, that most applications compiled against the preview will break and need to be recompiled against RTM.

Accordingly, we’ve updated both the MSDN documentation for JSRT and the Code Gallery hosting sample.

You can always reach me on Twitter here.

JsRT: Handling exceptions

The last major conceptual topic to cover for JsRT is how exceptions are handled.

Internally, Chakra uses C++ exception handling to handle both JavaScript exceptions and internal engine exceptions. However, even though the host might also be using C++ exception handling, the JsRT API surface enforces a strict separation between the host and Chakra when it comes to exceptions. Chakra exceptions will never cross over into the host (i.e. they will always be caught at the API boundary), and host exceptions should never cross over into the Chakra engine. Thus, hosts need to guard any callbacks to ensure that internal host exceptions don’t escape into Chakra.

OK, so, then how do exceptions work?

When a JavaScript exception occurs during script execution or during script compilation, and the exception is not handled in the script itself (i.e. the exception makes it to a JsRT API boundary), the containing runtime is put into an exception state. While in the exception state, no code can run in the runtime and all API calls will fail (with the error code JsErrorInExceptionState). This will continue until the host retrieves and clears the exception using the JsGetAndClearException API. This API will return an object representing the JavaScript value thrown (or the compile exception if the error occurred during compilation), and the runtime will be free to run code. How the host handles the exception is up to the host.

If the host is in the middle of a callback from Chakra, the host can also just return from the callback without clearing the runtime from an exception state. This will cause the JavaScript exception to be re-thrown when control passes back to the JavaScript engine.

If the host is in the middle of a callback and wants to “throw” a JavaScript exception, it can set the runtime into an exception state using JsSetException and then return from the callback. Just as above, the exception will be thrown in JavaScript once control passes back to the Chakra engine.

You should also follow me on Twitter here.

JsRT: Memory management

Yikes! It’s been longer than I thought it’s been since I last wrote on JsRT. Sorry about that, we’ve been a little busy.

With the two major concepts, runtimes and contexts, covered, there were a few additional things that need to be addressed for hosts that want to use JsRT. Probably the most important is how memory management is coordinated between Chakra and the host.

As you know, JavaScript is a garbage collected language, and everything you allocate through the JsRT API (with the exception of runtimes) is managed by the Chakra garbage collector. References will continue to live only as long as the garbage collector thinks they are “alive.” Once the GC thinks a reference is dead, the next collection will free up the memory and the reference will become invalid. The garbage collector looks in two places when determining if a reference is alive:

  1. The runtime’s garbage collected heap.
  2. The stack of the runtime’s current thread.

So a reference to a JavaScript value that is stored inside of another JavaScript value or in a local variable on the stack will always be seen by the garbage collector. But if a host stores a reference somewhere where the GC isn’t going to look (for example, in a host-allocated heap), then the reference will not be seen by the garbage collector and may result in premature collection of values that are still in use by the host. (When relying on a stack reference to keep a reference alive, you have to be extra careful–some language compilers (such as VC++) will optimize away stack variables where possible.)

If a host is going to store a reference where the GC can’t see it, it will need to manually add a reference to the object itself by calling JsAddRef. This will ensure the object will not go away until JsRelease is called. Calls to JsAddRef/JsRelease have to be paired–unbalanced calls will result in objects being collected too soon or staying alive forever.

You should also follow me on Twitter here.

JsRT: Execution Contexts

Last time, I covered runtimes, this time I want to briefly cover execution contexts. While a runtime owns all the machinery needed to execute code (heap, GC, JIT, etc.), it can’t just execute code on its own–it has to execute the code within a particular context. Each context shares its resources with other contexts in the runtime, but it has one crucial thing all to itself–the global object and everything that sits under it. So while code executed in two contexts that belong to the same runtime may use the same heap, they are nonetheless unable to see or affect one another at the language level. Contexts are effectively totally isolated from each other. Because objects created in a context are tied to that context’s unique global object, an object created in one context cannot be passed in to another context. The JsRT APIs check all incoming objects to ensure that they match the context being used and will error if they don’t.

To simplify the JsRT API, most of the APIs assume an ambient execution context. Once you set the current context on a thread using JsSetCurrentContext, all APIs will assume that context until you call JsSetCurrentContext again (APIs will return a JsErrorNoCurrentContext error if there isn’t a context that’s been set current on the thread). Contexts are tied to their parent runtime’s thread–making a context current on a thread means that that runtime becomes current on that thread. If the runtime happens to be active on another thread at the time, then setting the current context will fail.

Within a thread, however, calls into contexts can be nested. So, for example, a runtime r1 can create two contexts c1 and c2. It can then run a script in c1 which calls back into the host. The host callback can then set c2 as the current context and run some more code, provided that it restores c1 as the current context when it’s done. So it’s legal to run code in c2 while c1 is on the stack, you just have to make sure that you clean up when you’re done.

Finally, from a host’s perspective the most important thing to remember regarding contexts is that if you have host objects that you want to project into the JavaScript space for scripts to use, you have to do it for each context you create. There’s currently no way to say something like, “I want this object to appear in all contexts I create.”

You should also follow me on Twitter here.