//test.cpp
#include "stdafx.h"
#include <jsapi.h>
#include <js/Initialization.h>
#include "Test.h"
// A standard set of ClassOps for globals. This includes hooks to resolve
// standard JavaScript builtin types to give a more full-featured shell.
const JSClassOps DefaultGlobalClassOps = {
nullptr, // addProperty
nullptr, // deleteProperty
nullptr, // enumerate
JS_NewEnumerateStandardClasses, // newEnumerate
JS_ResolveStandardClass, // resolve
JS_MayResolveStandardClass, // mayResolve
nullptr, // finalize
nullptr, // call
nullptr, // hasInstance
nullptr, // construct
JS_GlobalObjectTraceHook // trace
};
// Create a simple Global object. A global object is the top-level 'this' value
// in a script and is required in order to compile or execute JavaScript.
JSObject* CreateGlobal(JSContext* cx) {
JS::CompartmentOptions ops;
static JSClass GlobalClass = { "global", JSCLASS_GLOBAL_FLAGS, &DefaultGlobalClassOps };
return JS_NewGlobalObject(cx, &GlobalClass, nullptr, JS::FireOnNewGlobalHook, ops);
}
// Initialize the JS environment, create a JSContext and run the example
// function in that context. By default the self-hosting environment is
// initialized as it is needed to run any JavaScript). If the 'initSelfHosting'
// argument is false, we will not initialize self-hosting and instead leave
// that to the caller.
bool RunExample(bool(*task)(JSContext*), bool initSelfHosting) {
if (!JS_Init()) {
return false;
}
JSContext* cx = JS_NewContext(JS::DefaultHeapMaxBytes);
if (!cx) {
return false;
}
if (initSelfHosting && !JS::InitSelfHostedCode(cx)) {
return false;
}
if (!task(cx)) {
return false;
}
JS_DestroyContext(cx);
JS_ShutDown();
return true;
}
//This example illustrates the bare minimum you need to do to execute a
//JavaScript program using embedded SpiderMonkey. It does no error handling and
//simply exits if something goes wrong.
//
//The above parts of this example that are reused in many simple embedding examples.
//
//To use the interpreter you need to create a context and a global object, and
//do some setup on both of these. You also need to enter a "request" (lock on
//the interpreter) and a "compartment" (environment within one global object)
//before you can execute code.
static bool ExecuteCodePrintResult(JSContext* cx, const char* code) {
JS::CompileOptions options(cx);
options.setFileAndLine("noname", 1);
JS::RootedValue rval(cx);
if (!JS::Evaluate(cx, options, code, strlen(code), &rval)) {
return false;
}
/*
* There are many ways to display an arbitrary value as a result. In this
* case, we know that the value is a string because of the expression that we
* executed, so we can just print the string directly.
*/
printf("%s\n", JS_EncodeString(cx, rval.toString()));
return true;
}
static bool HelloExample(JSContext* cx) {
JSAutoRequest ar(cx);
JS::RootedObject global(cx, CreateGlobal(cx));
if (!global) {
return false;
}
JSAutoCompartment ac(cx, global);
/*
* The 'js' delimiter is meaningless, but it's useful for marking C++ raw
* strings semantically.
*/
return ExecuteCodePrintResult(cx, R"js(`hello world, it is ${new Date()}`)js");
}
int main()
{
if (!RunExample(HelloExample)) {
return 1;
}
return 0;
}