-
Notifications
You must be signed in to change notification settings - Fork 3
Contexts
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;