Skip to content
Craig Minihan edited this page Dec 9, 2016 · 20 revisions

A context is a scope within a SpiderMonkey runtime. When you create a rs::jsapi::Context you get a context in which to run your JavaScript code. You can create many contexts within your application, each one is independent of the others.

In this example we create two contexts and define global variables in each:

#include "libjsapi.h"
int main() {
  if (true) {
      rs::jsapi::Context cx1;
  
      // create a global variable in the default context
      cx1.Evaluate("var myVar = 'hello world';");
  }

  // create another global variable in another context
  if (true) {
      rs::jsapi::Context cx2;
      cx2.Evaluate("var myVar = 'lorem ipsum';");
  }
}

The two myVar variables are completely separate, defined only within the scope of their own contexts. It is not possible to refer to a variable from a different context from JavaScript code.

If your application has more than one thread then you can create contexts within those threads and execute the JavaScript code in a thread-safe manner.

Each Context is bound to your hosting application's thread for the lifetime of the context. Therefore you can't have more than one context instance per thread. Eagle eyed developers will have noticed the contexts in the example above are created inside if () {} blocks for this reason.

The rs::jsapi::Context class implements the following methods for executing JavaScript code:

  bool Evaluate(const char* script);
  bool Evaluate(const char* script, Value& result);
  bool Call(const char* name);
  bool Call(const char* name, const FunctionArguments& args);
  bool Call(const char* name, Value& result);
  bool Call(const char* name, const FunctionArguments& args, Value& result);

The Evaluate methods allow you to define objects, arrays, functions, numbers and execute arbitrary JavaScript code. The Call methods are used to invoke JavaScript (or even native) functions from C++.

Assuming we have a Context defined in our application then we can get a result from JavaScript in C++ by invoking:

  rs::jsapi::Value result(cx);
  cx.Evaluate("(function(){return 42;})()", result);

The value in result should be 42 once the script has executed:

  std::cout << result.toInt32() << std::endl;

And we can invoke a JavaScript function too:

  cx.Evaluate("var myfunc = function() { return 42; }");
  rs::jsapi::Value result(cx);
  cx.Call("myfunc", result);
  std::cout << result.toInt32() << std::endl;

This example will yield the value 42 on stdout as before. However since we have defined a named function we can invoke it as many times as we want:

  int total = 0;
  cx.Evaluate("var myfunc = function() { return 42; }");
  rs::jsapi::Value result(cx);
  for (int i = 0; i < 10; ++i) {
    cx.Call("myfunc", result);
    total += result.toInt32();
  }
  std::cout << total << std::endl;
Clone this wiki locally