Skip to content
Craig Minihan edited this page Apr 20, 2015 · 20 revisions

A context is a scope within a SpiderMonkey runtime. When you create a rs::jsapi::Runtime you automatically get a default context in which to run your JavaScript code. If you don't need to run multiple instances of SpiderMonkey inside your application then you may never need to create a context directly.

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

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

  // create another global variable in another context
  auto context = rt.NewContext();
  context->Evaluate("var myVar = 'lorem ipsum';");

  return 0;
}

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.

Both the rs::jsapi::Runtime and rs::jsapi::Context classes implement roughly the same interface 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 Runtime defined in our application then we can get a result from JavaScript in C++ by invoking:

  rs::jsapi::Value result(rt);
  rt.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:

  rt.Evaluate("var myfunc = function() { return 42; }");
  rs::jsapi::Value result(rt);
  rt.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;
  rt.Evaluate("var myfunc = function() { return 42; }");
  rs::jsapi::Value result(rt);
  for (int i = 0; i < 10; ++i) {
    rt.Call("myfunc", result);
    total += result.toInt32();
  }
  std::cout << total << std::endl;

Clone this wiki locally