Spidermonkey is a JavaScript runtime that is embeddable in C/C++/Rust projects and allows you to interpret JavaScript and define bindings for JavaScript.

In this example we will see how to execute a script using Spidermonkey and get information about the execution. The prerequisites for this project are some knowledge of C/C++.

#include <js/Initialization.h> // JS_InitWithFailureDiagnostic, JS_Shutdown
#include <jsapi.h> // JS_NewContext

#include <js/CompilationAndEvaluation.h> // EvaluateUtf8Path
#include <js/CompileOptions.h> // OwningCompileOptions

namespace global {
    // describe the global object to spidermonkey
    static JSClass globalClass = {
      "global",
      JSCLASS_GLOBAL_FLAGS,
      &JS::DefaultGlobalClassOps,
    };
};

int main(int argc, const char* argv[]) {
    auto diagnosis = JS_InitWithFailureDiagnostic();
    if (diagnosis) {
        std::fprintf(stderr, diagnosis);
        return EXIT_FAILURE;
    }
    // creates an execution context
    JSContext *ctx = JS_NewContext(JS::DefaultHeapMaxBytes);

    // initialize the parts of spidermonkey that are written in JavaScript
    JS::InitSelfHostedCode(ctx);

    // set up boundaries for objects in the execution context
    JS::RealmOptions options;
    JS::RootedObject global(ctx, JS_NewGlobalObject(ctx, &global::globalClass, nullptr, JS::FireOnNewGlobalHook, options));

    // enter the boundaries for the execution context
    JSAutoRealm ar(ctx, global);

    // evaluate the test.js script and store the result in rval
    JS::RootedValue rval(ctx);
    JS::OwningCompileOptions compilationOptions(ctx);
    JS::EvaluateUtf8Path(ctx, compilationOptions, "test.js", &rval);

    // If an exception was encountered please print it.
    // E.g. syntax error 
    if (JS_IsExceptionPending(ctx)) {
      JS::ExceptionStack exnStack(ctx);
      JS::StealPendingExceptionStack(ctx, &exnStack);
      JS::ErrorReportBuilder builder(ctx);
      builder.init(ctx, exnStack, JS::ErrorReportBuilder::NoSideEffects);
      JS::PrintError(ctx, stderr, builder, false);
    }

    // tear down the execution context and stops Spidermonkey
    JS_DestroyContext(ctx);
    JS_ShutDown();
}