JSAPI User Guide

  • Revision slug: SpiderMonkey/JSAPI_User_Guide
  • Revision title: JSAPI User Guide
  • Revision id: 298238
  • Created:
  • Creator: and.selm
  • Is current revision? No
  • Comment

Revision Content

This document explains how to embed SpiderMonkey, the Mozilla JavaScript engine, in your C/C++ program.

JavaScript is widely used for client-side scripts that run in the browser. But Mozilla's JavaScript engine is a library that can be linked into any C/C++ program, not just a browser. Many applications can benefit from scripting. These programs can execute JavaScript code from C using the SpiderMonkey API.

Note: The FOSS wiki page contains a few links to other libraries and programs that can make life easier when using Spidermonkey and JSAPI.

What SpiderMonkey does

The JavaScript engine compiles and executes scripts containing JavaScript statements and functions. The engine handles memory allocation for the objects needed to execute scripts, and it cleans up—garbage collects—objects it no longer needs.

SpiderMonkey supports versions 1.0 through 1.8 of the JavaScript language. JS 1.3 and later conform to the ECMAScript specification, ECMA 262-3. Later versions also contain Mozilla extensions such as array comprehensions and generators. SpiderMonkey also supports E4X (optionally).

The word JavaScript may bring to mind features such as event handlers (like onclick), DOM objects, window.open, and XMLHttpRequest. But in Mozilla, all of these features are actually provided by other components, not the SpiderMonkey engine itself. SpiderMonkey provides a few core JavaScript data types—numbers, strings, Arrays, Objects, and so on—and a few methods, such as Array.push. It also makes it easy for each application to expose some of its own objects and functions to JavaScript code. Browsers expose DOM objects. Your application will expose objects that are relevant for the kind of scripts you want to write. It is up to the application developer to decide what objects and methods are exposed to scripts.

Hello world

Using the SpiderMonkey library

Your application can use SpiderMonkey like any other C/C++ library. To build SpiderMonkey from source, see SpiderMonkey Build Documentation. You can build SpiderMonkey as a static library or as a shared library.

Some platforms (such as Debian Linux) provide SpiderMonkey as a prebuilt package; this can be easier to install but harder to debug. The XULRunner SDK also contains a prebuilt SpiderMonkey and the according header files and import libraries.

C/C++ code accesses SpiderMonkey via the JSAPI, by including the header "jsapi.h". The JSAPI provides functions for setting up the JavaScript runtime, compiling and executing scripts, creating and examining JavaScript data structures, handling errors, enabling security checks, and debugging scripts.

An overview of JSAPI functionality follows. For more details, see the JSAPI Reference.

The SpiderMonkey universe

In order to run any JavaScript code in SpiderMonkey, an application must have three key elements: a JSRuntime, a JSContext, and a global object. This section describes what these things are. The next section explains how to set them up, using JSAPI functions.

Runtimes. A JSRuntime, or runtime, is the space in which the JavaScript variables, objects, scripts, and contexts used by your application are allocated. Every JSContext and every object in an application lives within a JSRuntime. They cannot travel to other runtimes or be shared across runtimes. Most applications only need one runtime.

Contexts. A JSContext, or context, is like a little machine that can do many things involving JavaScript code and objects. It can compile and execute scripts, get and set object properties, call JavaScript functions, convert JavaScript data from one type to another, create objects, and so on. Almost all JSAPI functions require a JSContext * as the first argument, just like most <stdio.h> functions require a FILE *.

There is a close association between contexts and threads. Simple, single-threaded applications can use a single context for everything. But each context can only do one thing at a time, so in a multithreaded application, only one thread at a time should use any given context. Such an application typically has one context per thread. JavaScript objects, on the other hand, are not permanently associated with the script, thread, or context that created them. They can be shared among many scripts or even many threads, as shown in the figure below.

Figure 1.1 illustrates the relationship of scripts to the runtime, contexts, and objects.

Figure 1.1

Image:Over3.gif

Global objects. Lastly, the global object contains all the classes, functions, and variables that are available for JavaScript code to use. Whenever JavaScript code does something like window.open("http://www.mozilla.org/"), it is accessing a global property, in this case window. JSAPI applications have full control over what global properties scripts can see. The application starts out by creating an object and populating it with the standard JavaScript classes, like Array and Object. Then it adds whatever custom classes, functions, and variables (like window) the application wants to provide; see Custom objects below. Each time the application runs a JS script (using, for example, JS_EvaluateScript), it provides the global object for that script to use. As the script runs, it can create global functions and variables of its own. All of these functions, classes, and variables are stored as properties of the global object.

A minimal example

Each of the three key elements described in the previous section requires a few JSAPI calls:

  • The runtime: Use JS_NewRuntime to create it and JS_DestroyRuntime to clean it up when you're done. When your application is done with SpiderMonkey altogether, use JS_ShutDown to free any remaining cached resources. (This is a mere nicety if the process is about to exit anyway. But as that is not always the case, calling JS_Shutdown is a good habit to get into.)

  • The context: Use JS_NewContext and JS_DestroyContext. For maximum ECMAScript standard compliance, applications should also use JS_SetOptions to enable JSOPTION_VAROBJFIX. To get the latest JavaScript language features, applications may use JS_SetVersion. Error reporting is also per-context and is enabled using JS_SetErrorReporter.

  • The global object: To create this object, you first need a JSClass with the JSCLASS_GLOBAL_FLAGS option. The example below defines a very basic JSClass (named global_class) with no methods or properties of its own. Use JS_NewGlobalObject to create a global object. Use JS_InitStandardClasses to populate it with the standard JavaScript globals.

This may seem like a lot of pieces for a simple application. It amounts to about 50 lines of code, as shown below. But the JSAPI is designed to scale to applications that need many threads, many contexts, and many global objects. It is a fine-grained API, supporting many different combinations of the parts, and giving applications precise control over how SpiderMonkey behaves.

Here is the boilerplate code necessary for a minimal JSAPI application. It contains everything described above.

/*
 * This define is for Windows only, it is a work-around for bug 661663.
 */
#ifdef _MSC_VER
# define XP_WIN
#endif
#include "jsapi.h"
/* The class of the global object. */
static JSClass global_class = { "global", JSCLASS_GLOBAL_FLAGS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JSCLASS_NO_OPTIONAL_MEMBERS };
/* The error reporter callback. */
void reportError(JSContext *cx, const char *message, JSErrorReport *report) {
     fprintf(stderr, "%s:%u:%s\n", report->filename ? report->filename : "<no filename="">", (unsigned int) report->lineno, message);

}

int main(int argc, const char *argv[]) {
    /* JS variables. */
    JSRuntime *rt;
    JSContext *cx;
    JSObject *global;
    /* Create a JS runtime. */
    rt = JS_NewRuntime(8L * 1024L * 1024L);
    if (rt == NULL)
       return 1;
    /* Create a context. */
    cx = JS_NewContext(rt, 8192);
    if (cx == NULL)
       return 1;
    JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
    JS_SetVersion(cx, JSVERSION_LATEST);
    JS_SetErrorReporter(cx, reportError);
    /* Create the global object in a new compartment. */
    global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
    if (global == NULL)
       return 1;
    /* Populate the global object with the standard globals, like Object and Array. */
    if (!JS_InitStandardClasses(cx, global))
       return 1;

   /* Your application code here. This may include JSAPI calls to create your own custom JS objects and run scripts. */

   JS_DestroyContext(cx);
   JS_DestroyRuntime(rt);
   JS_ShutDown();
   return 0;
}
</no>

A typical JSAPI application should also run garbage collection periodically. An application can do this by periodically calling JS_MaybeGC.

Multithreaded applications have additional basic requirements, including build requirements. See JS_THREADSAFE.

Native functions

Much of the rest of this guide explains how to expose custom functionality to scripts. The simplest way to start is by exposing a global native function.

Native functions are implemented in C/C++ but can be called from JavaScript just like any other function. The native function's signature must match JSNative.

#include <stdlib.h>
#include <time.h>
#include "jsapi.h"

/* A simple JS wrapper for the rand() function, from the C standard library.
   This example shows how to return a number from a JSNative.
   This is nearly the simplest possible JSNative function. */
JSBool myjs_rand(JSContext *cx, uintN argc, jsval *vp)
{
    JS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL(rand()));
    return JS_TRUE;
}

/* A wrapper for the srand() function, from the C standard library.
   This example shows how to handle optional arguments. */
JSBool myjs_srand(JSContext *cx, uintN argc, jsval *vp)
{
    uint32 seed;

    if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/u", &seed))
        return JS_FALSE;

    /* If called with no arguments, use the current time as the seed. */
    if (argc == 0)
        seed = time(NULL);

    srand(seed);

    JS_SET_RVAL(cx, vp, JSVAL_VOID);  /* return undefined */
    return JS_TRUE;
}

/* A wrapper for the system() function, from the C standard library.
   This example shows how to report errors. */
JSBool myjs_system(JSContext *cx, uintN argc, jsval *vp)
{
    JSString* str;
    char *cmd;
    int rc;

    if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "s", &str))
        return JS_FALSE;

    cmd = JS_EncodeString(cx, str);
    rc = system(cmd);
    JS_free(cx, cmd);
    if (rc != 0) {
        /* Throw a JavaScript exception. */
        JS_ReportError(cx, "Command failed with exit code %d", rc);
        return JS_FALSE;
    }

    JS_SET_RVAL(cx, vp, JSVAL_VOID);  /* return undefined */
    return JS_TRUE;
}

Each JSNative has the same signature, regardless of what arguments it expects to receive from JavaScript.

The JavaScript arguments to the function are given in argc and vp. argc tells how many actual arguments the caller passed, and JS_ARGV(cx, vp) returns an array of those arguments. The arguments do not have native C/C++ types like int and float; rather, they are jsvals, JavaScript values. The native function uses JS_ConvertArguments to convert the arguments to C/C++ types and store them in local variables. The native function uses JS_SET_RVAL(cx, vp, val) to store its JavaScript return value.

On success, a JSNative must call JS_SET_RVAL and return JS_TRUE. The value passed to JS_SET_RVAL is returned to the JavaScript caller.

On failure, a JSNative calls an error-reporting function, in this case JS_ReportError, and returns JS_FALSE. This causes a JavaScript exception to be thrown. The caller can catch the exception using a JavaScript try/catch statement.

To make native functions callable from JavaScript, declare a table of JSFunctionSpecs describing the functions. Then call JS_DefineFunctions.

static JSFunctionSpec myjs_global_functions[] = {
    JS_FS("rand",   myjs_rand,   0, 0),
    JS_FS("srand",  myjs_srand,  0, 0),
    JS_FS("system", myjs_system, 1, 0),
    JS_FS_END
};

    ...
    if (!JS_DefineFunctions(cx, global, myjs_global_functions))
        return JS_FALSE;
    ...

Once the functions are defined in global, any script that uses global as the global object can call them, just as any web page can call alert. In the environment we have created, the "hello world" script looks like this:

system("echo hello world");

JSAPI Concepts

This section aims to fill in the major gaps in the picture of the JSAPI presented so far. To do anything useful with SpiderMonkey, you must read all three sections.

JavaScript values

Main article: jsval

JavaScript is a dynamically typed language: variables and properties do not have a type that is fixed at compile time. How can a statically typed language, like C or C++, in which all variables have types, interact with JavaScript? The JSAPI provides a data type, jsval, which can contain JavaScript values of any type. A jsval can be a number, a string, a boolean value, a reference to an object (like an Object, Array, Date, or Function), or one of the special values null or undefined.

For integers and boolean values, a jsval contains the value itself. In other cases, the jsval is a pointer to an object, string, or number.

Warning: Like C/C++ pointers, and unlike JavaScript vars, a jsval is not automatically initialized to a safe value, and can become a dangling pointer!

A dangling pointer is a pointer that used to point to a valid object, but no longer does because the object no longer exists. Using a dangling pointer can crash a C/C++ program (or worse). In the case of jsval, the JavaScript garbage collector recycles objects, strings, and numbers that don't appear to be in use, and a jsval by itself does not protect its referent from the garbage collector. See Garbage collection below for crucial information on how to use jsvals safely.

The JSAPI includes macros that test the JavaScript data type of a jsval. These are:

If a jsval points to a JSObject, jsdouble, or JSString, you can cast the jsval to its underlying data type using JSVAL_TO_OBJECT, JSVAL_TO_DOUBLE, and JSVAL_TO_STRING, respectively. This is useful in some cases where your application or a JSAPI function requires a variable or argument of a specific data type, rather than a jsval. Similarly, you can cast a JSObject, jsdouble, or JSString pointer to a jsval using OBJECT_TO_JSVAL, DOUBLE_TO_JSVAL, or STRING_TO_JSVAL.

Garbage collection

As it runs, JavaScript code implicitly allocates memory for objects, strings, variables, and so on.  Garbage collection is the process by which the JavaScript engine detects when those pieces of memory are no longer reachable—that is, they could not possibly ever be used again—and reclaims the memory.

Garbage collection has two important consequences for JSAPI applications. First, the application must be very careful to ensure that any values it needs are GC-reachable. The garbage collector is rather eager about its job. Any object you leave lying around will be destroyed if you don't tell the JSAPI you're still using it. Second, the application should take steps to reduce the performance impact of garbage collection.

Keeping objects alive

If your JSAPI application crashes, it is likely due to a GC-related error. The application must ensure that the garbage collector can reach all the objects, numbers, and strings that are still being used. Otherwise, the GC will free the memory occupied by those values, leading to a probable crash the next time your program tries to use them.

There are many ways to ensure that a value is GC-reachable.

  • If you just need the value to remain reachable for the duration of a JSNative call, store it in *rval or an element of the argv array. The values stored in those locations are always reachable. To get extra argv slots, use JSFunctionSpec.extra.
  • If a custom object needs certain values to remain in memory, just store the values in properties of the object. As long as the object is reachable, its properties will remain reachable. If these values must not be accessible from JavaScript, use reserved slots instead. Or store the values in private data and implement JSClass.mark.
  • To keep a value alive permanently, store it in a GC root.

Still, GC bugs do occur. These two functions, both available only in DEBUG builds, are especially useful for debugging GC-related crashes:

  • Use JS_SetGCZeal to enable extra garbage collection. GC zeal usually causes a GC-related crash to occur much sooner (closer to its cause) and more reliably. It's for development and debugging only, because the extra garbage collection makes JS very slow.
  • Use JS_DumpHeap to dump the SpiderMonkey heap or specific interesting parts of it.

See SpiderMonkey Garbage Collection Tips for more details.

GC performance

Overly frequent garbage collection can be a performance issue. Some applications can reduce the frequency of garbage collection simply by increasing the initial size of the JSRuntime.

Perhaps the best technique is to perform garbage collection during idle time, when it is least likely to have any impact on the user. By default, the JavaScript engine performs garbage collection when it has no other choice except to grow the process. This means that garbage collection typically happens when memory-intensive code is running, perhaps the worst possible time. An application can trigger garbage collection at a more convenient time by calling JS_GC or JS_MaybeGC. JS_GC forces garbage collection. JS_MaybeGC performs garbage collection only if it is likely to reclaim a worthwhile amount of memory.

Errors and exceptions

The importance of checking the return value of JSAPI functions, of course, goes without saying. Almost every JSAPI function that takes a JSContext * argument can fail. The system might run out of memory. There might be a syntax error in a script. Or a script might explicitly throw an exception.

The JavaScript language has exceptions, and C++ has exceptions, but they are not the same thing. SpiderMonkey does not use C++ exceptions for anything. JSAPI functions never throw C++ exceptions, and when SpiderMonkey calls an application callback, the callback must not throw a C++ exception.

Throwing and catching exceptions

We have already seen one example of how to throw an exception from a JSNative function. Simply call JS_ReportError, with printf-style arguments, and return JS_FALSE.

    rc = system(cmd);
    if (rc != 0) {
        /* Throw a JavaScript exception. */
        JS_ReportError(cx, "Command failed with exit code %d", rc);
        return JS_FALSE;
    }

This is very much like the JavaScript statement throw new Error("Command failed with exit code " + rc);. Again, note that calling JS_ReportError does not cause a C++ exception to be thrown. It only creates a new JavaScript Error object and stores it in the context as the current pending exception. The application must also return JS_FALSE.

Once the C/C++ function returns JS_FALSE, the JavaScript engine starts unwinding the JavaScript stack, looking for a catch or finally block to execute. But SpiderMonkey's stack unwinding never removes application's C/C++ functions from the stack. Instead, SpiderMonkey simply returns JS_FALSE or NULL to the application, which can then handle the error as it chooses—or just return JS_FALSE to let it propagate further up the stack.

Several more examples of throwing and catching exceptions can be found in the JSAPI Phrasebook.

Error reports

TODO your custom errorreporter

TODO when errors are reported

Automatic handling of uncaught exceptions

The JS_Compile*, JS_Call*, JS_Execute*, and JS_Evaluate* functions automatically pass exceptions to the error reporter in certain cases. Each of these functions checks, just before it returns, to see if an exception is pending in the current JSContext. If so, it then checks to see if there is any other JavaScript script or function on the stack in that JSContext. If so, then the exception might yet be caught, so SpiderMonkey does nothing and returns JS_FALSE, allowing the exception to propagate. But if nothing is on the JavaScript stack, then the uncaught exception is passed to the error reporter and the pending exception is cleared.

The basic consequence is that top-level application code can just set an error reporter and start calling JSAPI functions. It never has to explicitly handle uncaught exceptions; the error reporter is automatically called. An application can disable automatic uncaught-exception handling using the JSOPTION_DONT_REPORT_UNCAUGHT option, but it must then deal with uncaught exceptions explicitly by calling JS_IsExceptionPending, JS_GetPendingException, JS_ReportPendingException, and/or JS_ClearPendingException whenever a JSAPI function returns JS_FALSE or NULL.

Uncatchable errors

Another way for a JSNative callback to report an error is like this:

    if (p == NULL) {
        JS_ReportOutOfMemory(cx);
        return JS_FALSE;
    }

This does something subtly different from what JS_ReportError does.

Most errors, including those raised by JS_ReportError, are represented as JavaScript exceptions and thus interact with the JavaScript exception-handling language features, try, catch, and finally. However, in some cases we do not want scripts to be able to catch an error; we want script execution to terminate right away. If the system runs out of memory in the middle of a script, we do not want finally blocks to execute, because almost anything a script does requires at least a little memory, and we have none. If a script has been running too long and we want to kill it, it's no good to throw an exception—the script could just catch it and keep going.

Therefore JS_ReportOutOfMemory(cx) does not set the pending exception. It is an uncatchable error.

If SpiderMonkey runs out of memory, or a JSAPI callback returns JS_FALSE without an exception pending, this is treated as an uncatchable error. The JavaScript stack is unwound in the normal way except that catch and finally blocks are ignored. The most recent JSAPI call returns JS_FALSE or NULL to the application.

An uncatchable error leaves the JSContext in a good state. It can be used again right away. The application does not have to do anything to “recover” from the error, as far as the JSAPI is concerned. (Of course, if the error is that the system is out of memory, that problem remains to be dealt with.)

Here is some example code that throws an uncatchable error.

    /* Call the error reporter, if any. This part is optional. */
    JS_ReportError(cx, "The server room is on fire!");
    JS_ReportPendingException(cx);

    /* Make sure the error is uncatchable. */
    JS_ClearPendingException(cx);
    return JS_FALSE;

 

 

More sample code

The following examples illustrate how to achieve a few different effects using the JSAPI.

Note that the most important example is in the "A minimal example" section above. More JSAPI code samples appear in the JSAPI Phrasebook.

Defining objects and properties

/* Statically initialize a class to make "one-off" objects. */
JSClass my_class = {
    "MyClass",

    /* All of these can be replaced with the corresponding JS_*Stub
       function pointers. */
    my_addProperty, my_delProperty, my_getProperty, my_setProperty,
    my_enumerate,   my_resolve,     my_convert,     my_finalize
};

JSObject *obj;

/*
 * Define an object named in the global scope that can be enumerated by
 * for/in loops.  The parent object is passed as the second argument, as
 * with all other API calls that take an object/name pair.  The prototype
 * passed in is null, so the default object prototype will be used.
 */
obj = JS_DefineObject(cx, globalObj, "myObject", &my_class, NULL,
                      JSPROP_ENUMERATE);

/*
 * Define a bunch of properties with a JSPropertySpec array statically
 * initialized and terminated with a null-name entry.  Besides its name,
 * each property has a "tiny" identifier (MY_COLOR, e.g.) that can be used
 * in switch statements (in a common my_getProperty function, for example).
 */
enum my_tinyid {
    MY_COLOR, MY_HEIGHT, MY_WIDTH, MY_FUNNY, MY_ARRAY, MY_RDONLY
};

static JSPropertySpec my_props[] = {
    {"color",       MY_COLOR,       JSPROP_ENUMERATE},
    {"height",      MY_HEIGHT,      JSPROP_ENUMERATE},
    {"width",       MY_WIDTH,       JSPROP_ENUMERATE},
    {"funny",       MY_FUNNY,       JSPROP_ENUMERATE},
    {"array",       MY_ARRAY,       JSPROP_ENUMERATE},
    {"rdonly",      MY_RDONLY,      JSPROP_READONLY},
    {0}
};

JS_DefineProperties(cx, obj, my_props);

/*
 * Given the above definitions and call to JS_DefineProperties, obj will
 * need this sort of "getter" method in its class (my_class, above).  See
 * the example for the "It" class in js.c.
 */
static JSBool
my_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    if (JSVAL_IS_INT(id)) {
        switch (JSVAL_TO_INT(id)) {
          case MY_COLOR:  *vp = . . .; break;
          case MY_HEIGHT: *vp = . . .; break;
          case MY_WIDTH:  *vp = . . .; break;
          case MY_FUNNY:  *vp = . . .; break;
          case MY_ARRAY:  *vp = . . .; break;
          case MY_RDONLY: *vp = . . .; break;
        }
    }
    return JS_TRUE;
}

Defining classes

This pulls together the above API elements by defining a constructor function, a prototype object, and properties of the prototype and of the constructor, all with one API call.

Initialize a class by defining its constructor function, prototype, and per-instance and per-class properties. The latter are called "static" below by analogy to Java. They are defined in the constructor object's scope, so that MyClass.myStaticProp works along with new MyClass().

JS_InitClass takes a lot of arguments, but you can pass NULL for any of the last four if there are no such properties or methods.

Note that you do not need to call JS_InitClass to make a new instance of that class—otherwise there would be a chicken-and-egg problem making the global object—but you should call JS_InitClass if you require a constructor function for script authors to call via new, and/or a class prototype object (MyClass.prototype) for authors to extend with new properties at run time. In general, if you want to support multiple instances that share behavior, use JS_InitClass.

protoObj = JS_InitClass(cx, globalObj, NULL, &my_class,

                        /* native constructor function and min arg count */
                        MyClass, 0,

                        /* prototype object properties and methods -- these
                           will be "inherited" by all instances through
                           delegation up the instance's prototype link. */
                        my_props, my_methods,

                        /* class constructor properties and methods */
                        my_static_props, my_static_methods);

Running scripts

/* These should indicate source location for diagnostics. */
char *filename;
uintN lineno;

/*
 * The return value comes back here -- if it could be a GC thing, you must
 * add it to the GC's "root set" with JS_AddRoot(cx, &thing) where thing
 * is a JSString *, JSObject *, or jsdouble *, and remove the root before
 * rval goes out of scope, or when rval is no longer needed.
 */
jsval rval;
JSBool ok;

/*
 * Some example source in a C string.  Larger, non-null-terminated buffers
 * can be used, if you pass the buffer length to JS_EvaluateScript.
 */
char *source = "x * f(y)";

ok = JS_EvaluateScript(cx, globalObj, source, strlen(source),
                       filename, lineno, &rval);

if (ok) {
    /* Should get a number back from the example source. */
    jsdouble d;

    ok = JS_ValueToNumber(cx, rval, &d);
    . . .
}

Calling functions

/* Call a global function named "foo" that takes no arguments. */
ok = JS_CallFunctionName(cx, globalObj, "foo", 0, 0, &rval);

jsval argv[2];

/* Call a function in obj's scope named "method", passing two arguments. */
argv[0] = . . .;
argv[1] = . . .;
ok = JS_CallFunctionName(cx, obj, "method", 2, argv, &rval);

JSContext

Because there is a certain amount of overhead associated with allocating and maintaining contexts, a JSAPI application should:

  1. Create only as many contexts as it needs at one time.
  2. Keep contexts for as long as they may be needed, rather than destroying and recreating them as needed.

If your application creates multiple runtimes, the application may need to know which runtime a context is associated with. In this case, use JS_GetRuntime.

Use JS_SetContextPrivate and JS_GetContextPrivate to associate application-specific data with a context.

Initializing built-in and global JS objects

For a complete list of built-in objects provided by SpiderMonkey, see JS_InitStandardClasses.

The global object that an application provides to scripts largely determines what those scripts can do. For example, the Firefox browser uses its own global object, window. To change the global object for your application, call JS_SetGlobalObject.

Creating and initializing custom objects

In addition to using the engine's built-in objects, you will create, initialize, and use your own JS objects. This is especially true if you are using the JS engine with scripts to automate your application. Custom JS objects can provide direct program services, or they can serve as interfaces to your program's services. For example, a custom JS object that provides direct service might be one that handles all of an application's network access, or might serve as an intermediary broker of database services. Or a JS object that mirrors data and functions that already exist in the application may provide an object-oriented interface to C code that is not otherwise, strictly-speaking, object-oriented itself. Such a custom object acts as an interface to the application itself, passing values from the application to the user, and receiving and processing user input before returning it to the application. Such an object might also be used to provide access control to the underlying functions of the application.

There are two ways to create custom objects that the JS engine can use:

  • Write a JS script that creates an object, its properties, methods, and constructor, and then pass the script to the JS engine at run time.
  • Embed code in your application that defines the object's properties and methods, call the engine to initialize a new object, and then set the object's properties through additional engine calls. An advantage of this method is that your application can contain native methods that directly manipulate the object embedding.

In either case, if you create an object and then want it to persist in the run time where it can be used by other scripts, you must root the object by calling JS_AddRoot or JS_AddNamedRoot. Using these functions ensures that the JS engine will keep track of the objects and clean them up during garbage collection, if appropriate.

Creating an object from a script

One reason to create a custom JS object from a script is when you only need an object to exist as long as the script that uses it is executing. To create objects that persist across script calls, you can embed the object code in your application instead of using a script.

Note: You can also use scripts to create persistent objects, too.

To create a custom object using a script:

  1. Define and spec the object. What is it intended to do? What are its data members (properties)? What are its methods (functions)? Does it require a run time constructor function?
  2. Code the JS script that defines and creates the object. For example: function myfun(){ var x = newObject(); . . . } NOTE: Object scripting using JavaScript occurs outside the context of embedding the JS engine in your applications. For more information about object scripting, see the Client-Side JavaScript Guide and the Server-Side JavaScript Guide. Embed the appropriate JS engine call(s) in your application to compile and execute the script. You have two choices: 1.) compile and execute a script with a single call to JS_EvaluateScript, JS_EvaluateUCScript or 2.) compile the script once with a call to JS_CompileScript or JS_CompileUCScript, and then execute it repeatedly with individual calls to JS_ExecuteScript. The "UC" versions of these calls provide support for Unicode-encoded scripts.

An object you create using a script only can be made available only during the lifetime of the script, or can be created to persist after the script completes execution. Ordinarily, once script execution is complete, its objects are destroyed. In many cases, this behavior is just what your application needs. In other cases, however, you will want object persistence across scripts, or for the lifetime of your application. In these cases you need to embed object creation code directly in your application, or you need to tie the object directly to the global object so that it persists as long as the global object itself persists.

Custom objects

An application can create a custom object without bothering with a JSClass:

  1. Implement the getters, setters, and methods for your custom object in C or C++.  Write a JSPropertyOp for each getter or setter.  Write a JSNative or JSFastNative for each method.
  2. Declare a JSPropertySpec array containing information about your custom object's properties, including getters and setters.
  3. Declare a JSFunctionSpec array containing information about your custom object's methods.
  4. Call JS_NewObject, JS_ConstructObject, or JS_DefineObject to create the object.
  5. Call JS_DefineProperties to define the object's properties.
  6. Call JS_DefineFunctions to define the object's methods.

JS_SetProperty can also be used to create properties on an object. The properties it creates do not have getters or setters; they are ordinary JavaScript properties.

Providing private data for objects

Like contexts, you can associate large quantities of data with an object without having to store the data in the object itself. Call JS_SetPrivate to establish a pointer to private data for the object, and call JS_GetPrivate to retrieve the pointer so that you can access the data. Your application is responsible for creating and managing this optional private data.

To create private data and associate it with an object:

  1. Establish the private data as you would a normal C void pointer variable.
  2. Call JS_SetPrivate, specify the object for which to establish private data, and specify the pointer to the data.

For example:

 JS_SetPrivate(cx, obj, pdata);

To retrieve the data at a later time, call JS_GetPrivate, and pass the object as an argument. This function returns the pointer to an object's private data:

 pdata = JS_GetPrivate(cx, obj);

Special topics

Unicode

To pass Unicode data between JavaScript and native code, represent the data in UTF-16 in memory. JavaScript strings, property names, and programs are all made up of jschars, which are 16-bit unsigned integers.

Many JSAPI functions operate on null-terminated, 8-bit char strings. These functions convert their char * arguments to 16-bit strings by zero-extending each 8-bit char to 16 bits—unless JS_C_STRINGS_ARE_UTF8 is defined or JS_SetCStringsAreUTF8 has been called, in which case each char * string is interpreted as UTF-8 Unicode text.

The JSAPI provides jschar-based versions of many API functions that operate on strings, object properties, and JavaScript code.

char-based function jschar-based function
Unicode data
JS_GetStringBytes {{obsolete_inline("js1.8.5")}} JS_GetStringChars
JS_NewString JS_NewUCString
JS_NewStringCopyN JS_NewUCStringCopyN
JS_NewStringCopyZ JS_NewUCStringCopyZ
JS_InternString JS_InternUCString, JS_InternUCStringN
JS_ReportErrorNumber JS_ReportErrorNumberUC
JS_ReportErrorFlagsAndNumber JS_ReportErrorFlagsAndNumberUC
Unicode property names
JS_DefineProperty JS_DefineUCProperty
JS_DefinePropertyWithTinyId JS_DefineUCPropertyWithTinyId
JS_DefineFunction JS_DefineUCFunction
JS_HasProperty JS_HasUCProperty
JS_LookupProperty JS_LookupUCProperty
JS_GetProperty JS_GetUCProperty
JS_GetPropertyAttributes JS_GetUCPropertyAttributes
JS_GetPropertyAttrsGetterAndSetter JS_GetUCPropertyAttrsGetterAndSetter
JS_SetProperty JS_SetUCProperty
JS_SetPropertyAttributes JS_SetUCPropertyAttributes
JS_DeleteProperty2 JS_DeleteUCProperty2
JS_AlreadyHasOwnProperty JS_AlreadyHasOwnUCProperty
Unicode JavaScript source
JS_CompileScript JS_CompileUCScript
JS_CompileScriptForPrincipals JS_CompileUCScriptForPrincipals
JS_CompileFunction JS_CompileUCFunction
JS_CompileFunctionForPrincipals JS_CompileUCFunctionForPrincipals
JS_EvaluateScript JS_EvaluateUCScript
JS_EvaluateScriptForPrincipals JS_EvaluateUCScriptForPrincipals

jschar-based functions work exactly like their char-based namesakes, except that where traditional functions take a char * argument, the Unicode versions take a jschar * argument, usually with a separate argument specifying the length of the string in jschars.

Compiled scripts

The easiest way to run a script is to use JS_EvaluateScript, which compiles and executes the script in one go.

But sometimes an application needs to run a script many times. In this case, it may be faster to compile the script once and execute it multiple times.

The JSAPI provides a type, JSScript, that represents a compiled script. The life cycle of a JSScript looks like this:

  • The application calls JS_ExecuteScript (or JS_ExecuteScriptPart) any number of times. It is safe to use a JSScript in multiple different contexts {{ Jsapi_todo("and different global objects?") }}, but only within the JSRuntime and thread in which it was created.

Here is some example code using a compiled script:

/*
 * Compile a script and execute it repeatedly until an
 * error occurs.  (If this ever returns, it returns false.
 * If there's no error it just keeps going.)
 */
JSBool compileAndRepeat(JSContext *cx, const char *filename)
{
    JSScript *script;

    script = JS_CompileFile(cx, JS_GetGlobalObject(cx), filename);
    if (script == NULL)
        return JS_FALSE;   /* compilation error */

    for (;;) {
        jsval result;

        if (!JS_ExecuteScript(cx, JS_GetGlobalObject(cx), script, &result))
            break;
        JS_MaybeGC(cx);
    }

    JS_DestroyScript(cx, script);
    return JS_FALSE;
}

Sometimes it is inconvenient for an application to manage the lifetime of each script. Failing to call JS_DestroyScript can lead to memory leaks, and calling it too soon can cause crashes.

An alternative is to tie the lifetime of the compiled script to the lifetime of a JavaScript object, and let the garbage collector destroy the script when it is no longer reachable. The JSAPI provides this feature via the JS_NewScriptObject function. The life cycle of a script using this feature is like this:

  • The application compiles some JavaScript code.
  • The application executes the compiled script any number of times.
  • As the application progresses, eventually it doesn't need the compiled script anymore, and the compiled script object becomes unreachable.
  • The garbage collector then eventually collects the unreachable script and its components.

Here is example code demonstrating the technique—but note that this case is not really complex enough to warrant the use of JS_NewScriptObject. The above example does the same thing more directly.

/*
 * Compile a script and execute it repeatedly until an
 * error occurs.  (If this ever returns, it returns false.
 * If there's no error it just keeps going.)
 */
JSBool compileAndRepeat(JSContext *cx, const char *filename)
{
    JSScript *script;
    JSObject *scriptObj;

    script = JS_CompileFile(cx, JS_GetGlobalObject(cx), filename);
    if (script == NULL)
        return JS_FALSE;   /* compilation error */

    scriptObj = JS_NewScriptObject(cx, script);
    if (scriptObj == NULL) {
        JS_DestroyScript(cx, script);
        return JS_FALSE;
    }

    if (!JS_AddNamedObjectRoot(cx, &scriptObj, "compileAndRepeat script object"))
        return JS_FALSE;

    for (;;) {
        jsval result;

        if (!JS_ExecuteScript(cx, JS_GetGlobalObject(cx), script, &result))
            break;
        JS_MaybeGC(cx);
    }

    JS_RemoveObjectRoot(cx, &scriptObj);  /* scriptObj becomes unreachable
                                             and will eventually be collected. */
    return JS_FALSE;
}

Security

Many applications use SpiderMonkey to run untrusted code. In designing this kind of application, it's important to think through the security concerns ahead of time. Your application will need to do several things.

  • Deploy security updates - Firefox automatically installs updates, so security fixes are deployed as soon as they are available. Unless you also regularly deploy SpiderMonkey security updates, a determined hacker could use publicly known bugs in the engine to attack your application. Note that the kind of attack we're talking about here is where a hacker uses JavaScript to attack the C++ code of the engine itself (or your embedding). The rest of the items in this list talk about security issues that arise within JavaScript itself, even if the engine is working properly.
  • Block simple denial-of-service attacks - A program like while(true){} should not hang your application. To stop execution of scripts that run too long, use JS_SetOperationCallback. Likewise, a function like function f(){f();} should not crash your application with a stack overflow. To block that, use JS_SetNativeStackQuota.
  • Control access to sensitive data - Your application might expose data to some scripts that other scripts should not be able to see. For example, you might let your customers write scripts that operate on their own data, but not other customers' data. These access rules must be enforced somehow.
  • Control access to dangerous functionality - Suppose your application has a method deleteUserAccount() which is meant to be used by administrators only. Obviously if untrusted code can use that method, you have a security problem.

The first two problems are important but fairly straightforward and will not be discussed further here. The rest of this section tells how you can control scripts' access to data and functionality.

The best security is no security (really)

Do you ever worry about your snake eating your mouse? No? If you don't have both a snake and a mouse, you don't have this problem.

Likewise, if your application doesn't have both untrusted users (snakes) and sensitive data or dangerous functionality that's exposed to JavaScript (mice), then you don't need to read any further. The functions and objects created by JS_InitStandardClasses are safe. They do not provide access to files, the network, or anything browser-related. The most sensitive information they expose to scripts is the current date and time.

Object-capabilities-based security

One way to keep a snake from eating a mouse is to keep the mouse and the snake in separate cages.

One way to keep user A from accessing user B's sensitive data or dangerous functions is to keep each user's code in a separate sandbox. That is, create a separate JSContext and global object for each user, and always run each script in the appropriate context. When setting up a new global object, simply don't define any functions the user shouldn't have access to. This approach is called object-capabilities security. To learn more about it, watch the movie or read the book.

The metaphor is misleading in one regard: the snake can't reach the mouse because there's a physical barrier in the way. With SpiderMonkey the situation is more subtle. There's no barrier; there's just no way to get there from here. How can a malicious script get a reference to an object from another sandbox? It might as well be in a parallel universe. Even global variables are per-sandbox. There is no getObjectFromOtherSandbox() function. Your application just needs to take care not to expose any such function to scripts.

In short, never pass one user's data and objects to another user's code, and you'll have no access control issues. SpiderMonkey won't do it if you don't.

Trade-offs. Object-capabilities security is security without run-time security checks. It is easy to implement, easy to reason about, and fast. But in fairness there are some drawbacks. First, the failure mode is pretty severe. If you do accidentally leak an object from one sandbox into another, the genie is out of the bottle. Once a malicious script gets a reference to a single object in a sandbox, it can use that object to get a reference to the sandbox's global object, and from there, almost any other object or function in that sandbox. There is no way to fix it except to destroy both sandboxes and start over. A second drawback is that the system doesn't automatically respond to changes in user privileges. Suppose user A is not an administrator, so you set up sandbox A with no administrator functionality. If you promote user A to be an admin, SpiderMonkey won't magically update sandbox A to have the administrator classes and functions you didn't define before. Your application will have to do that explicitly. Conversely, if you want to strip user A's administrator privileges, but you have already given administrator functions to user A's scripts, that's even worse. You have no choice but to destroy user A's sandbox and start over.

Fine-grained security

Another way to keep a snake from eating a mouse is to watch the snake constantly, and if it tries to eat the mouse, intervene.

SpiderMonkey is designed to support custom, application-defined security models. For example, the Firefox browser has a complex and powerful security model. Some JavaScript code ("chrome") has full access to the system. Scripts from web pages ("content") have very limited access. The same origin policy governs a script's access to data and functions from other web pages.

The SpiderMonkey security model is based on the Java principals security model. This model provides a common security interface, but the actual security implementation is up to you.

To use SpiderMonkey's fine-grained security features:

Tracing and Profiling

There are features provided by the JSAPI that make it easier to implement JavaScript tracers and profilers.

Function tracing

If you configure with --enable-trace-jscalls, you can use JS_SetFunctionCallback() to set up a C function to be called whenever a JavaScript function is about to be called, or has finished executing:

void funcTransition(const JSFunction *func,
                    const JSScript *scr,
                    const JSContext *const_cx,
                    JSBool entering)
{
  JSContext *cx = const_cast<JSContext*>(const_cx);
  JSString *name = JS_GetFunctionId((JSFunction*)func);
  const char *entExit;
  const char *nameStr;

  /* build a C string for the function's name */

  if (!name) {
    nameStr = "Unnamed function";
  } else {
    nameStr = JS_EncodeString(cx, name);
  }

  /* build a string for whether we're entering or exiting */

  if (entering) {
    entExit = "Entering";
  } else {
    entExit = "Exiting";
  }

  /* output information about the trace */

  printf("%s JavaScript function: %s at time: %ld", entExit, nameStr, clock());
} 

void enableTracing(JSContext *cx) {
  JS_SetFunctionCallback(cx, funcTransition);
}

void disableTracing(JSContext *cx) {
  JS_SetFunctionCallback(cx, NULL);
}

Revision Source

<p>This document explains how to embed <a href="/en/SpiderMonkey" title="en/SpiderMonkey">SpiderMonkey</a>, the Mozilla JavaScript engine, in your C/C++ program.</p>
<p>JavaScript is widely used for client-side scripts that run in the browser. But Mozilla's JavaScript engine is a library that can be linked into any C/C++ program, not just a browser. Many applications can benefit from scripting. These programs can execute JavaScript code from C using the SpiderMonkey API.</p>
<div class="note">
  <strong>Note:</strong> The <a class="internal" href="/En/SpiderMonkey/FOSS" title="En/SpiderMonkey/FOSS">FOSS</a> wiki page contains a few links to other libraries and programs that can make life easier when using Spidermonkey and JSAPI.</div>
<h2 id="What_SpiderMonkey_does" name="What_SpiderMonkey_does">What SpiderMonkey does</h2>
<p>The JavaScript engine compiles and executes scripts containing JavaScript statements and functions. The engine handles memory allocation for the objects needed to execute scripts, and it cleans up—garbage collects—objects it no longer needs.</p>
<p>SpiderMonkey supports versions 1.0 through 1.8 of the JavaScript language. JS 1.3 and later conform to the ECMAScript specification, ECMA 262-3. Later versions also contain Mozilla extensions such as array comprehensions and generators. SpiderMonkey also supports <a href="/en/E4X" title="en/E4X">E4X</a> (optionally).</p>
<p>The word <em>JavaScript</em> may bring to mind features such as event handlers (like <code><a href="/en/DOM/element.onclick" title="en/DOM/element.onclick">onclick</a></code>), <a href="/en/DOM" title="en/DOM">DOM</a> objects, <code><a href="/en/DOM/window.open" title="en/DOM/window.open">window.open</a></code>, and <code><a href="/en/DOM/XMLHttpRequest" title="en/XMLHttpRequest">XMLHttpRequest</a></code>. But in Mozilla, all of these features are actually provided by other components, not the SpiderMonkey engine itself. SpiderMonkey provides a few core JavaScript data types—numbers, strings, <code>Array</code>s, <code>Object</code>s, and so on—and a few methods, such as <code>Array.push</code>. It also makes it easy for each application to expose some of its own objects and functions to JavaScript code. Browsers expose DOM objects. Your application will expose objects that are relevant for the kind of scripts you want to write. It is up to the application developer to decide what objects and methods are exposed to scripts.</p>
<h2 id="Hello_world">Hello world</h2>
<h3 id="Using_the_SpiderMonkey_library" name="Using_the_SpiderMonkey_library">Using the SpiderMonkey library</h3>
<p>Your application can use SpiderMonkey like any other C/C++ library. To build SpiderMonkey from source, see <a href="/En/SpiderMonkey/Build_Documentation" title="en/SpiderMonkey_Build_Documentation">SpiderMonkey Build Documentation</a>. You can build SpiderMonkey as a static library or as a shared library.</p>
<p>Some platforms (such as Debian Linux) provide SpiderMonkey as a prebuilt package; this can be easier to install but harder to debug. The <a href="/en/Gecko_SDK" title="/en/Gecko_SDK">XULRunner SDK</a> also contains a prebuilt SpiderMonkey and the according header files and import libraries.</p>
<p>C/C++ code accesses SpiderMonkey via the JSAPI, by including the header <code>"jsapi.h"</code>. The JSAPI provides functions for setting up the JavaScript runtime, compiling and executing scripts, creating and examining JavaScript data structures, handling errors, enabling security checks, and debugging scripts.</p>
<p>An overview of JSAPI functionality follows. For more details, see the <a href="/en/SpiderMonkey/JSAPI_Reference" title="en/JSAPI_Reference">JSAPI Reference</a>.</p>
<h3 id="The_SpiderMonkey_universe">The SpiderMonkey universe</h3>
<p>In order to run any JavaScript code in SpiderMonkey, an application must have three key elements: a <code>JSRuntime</code>, a <code>JSContext</code>, and a global object. This section describes what these things are. The next section explains how to set them up, using JSAPI functions.</p>
<p><strong>Runtimes.</strong> A <code>JSRuntime</code>, or <em>runtime</em>, is the space in which the JavaScript variables, objects, scripts, and contexts used by your application are allocated. Every <code>JSContext</code> and every object in an application lives within a <code>JSRuntime</code>. They cannot travel to other runtimes or be shared across runtimes. Most applications only need one runtime.</p>
<p><strong>Contexts.</strong> A <code>JSContext</code>, or <em>context</em>, is like a little machine that can do many things involving JavaScript code and objects. It can compile and execute scripts, get and set object properties, call JavaScript functions, convert JavaScript data from one type to another, create objects, and so on. Almost all JSAPI functions require a <code>JSContext&nbsp;*</code> as the first argument, just like most <code>&lt;stdio.h&gt;</code> functions require a <code>FILE&nbsp;*</code>.</p>
<p>There is a close association between contexts and threads. Simple, single-threaded applications can use a single context for everything. But each context can only do one thing at a time, so in a multithreaded application, only one thread at a time should use any given context. Such an application typically has one context per thread. JavaScript objects, on the other hand, are <em>not</em> permanently associated with the script, thread, or context that created them. They can be shared among many scripts or even many threads, as shown in the figure below.</p>
<p>Figure 1.1 illustrates the relationship of scripts to the runtime, contexts, and objects.</p>
<div style="margin-left: 3em;">
  <p><strong><small>Figure 1.1</small></strong></p>
  <p><img alt="Image:Over3.gif" class="internal" src="/@api/deki/files/291/=Over3.gif" /></p>
</div>
<p><strong>Global objects.</strong> Lastly, the <em>global object</em> contains all the classes, functions, and variables that are available for JavaScript code to use. Whenever JavaScript code does something like <code><span class="nowiki">window.open("http://www.mozilla.org/")</span></code>, it is accessing a global property, in this case <code>window</code>. JSAPI applications have full control over what global properties scripts can see. The application starts out by creating an object and populating it with the standard JavaScript classes, like <code>Array</code> and <code>Object</code>. Then it adds whatever custom classes, functions, and variables (like <code>window</code>) the application wants to provide; see <a href="#Custom_objects">Custom objects</a> below. Each time the application runs a JS script (using, for example, <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_EvaluateScript" title="en/JS_EvaluateScript">JS_EvaluateScript</a></code>), it provides the global object for that script to use. As the script runs, it can create global functions and variables of its own. All of these functions, classes, and variables are stored as properties of the global object.</p>
<h3 id="A_minimal_example">A minimal example</h3>
<p>Each of the three key elements described in the previous section requires a few JSAPI calls:</p>
<ul>
  <li>
    <p>The runtime: Use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewRuntime" title="en/JS_NewRuntime">JS_NewRuntime</a></code> to create it and <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DestroyRuntime" title="en/JS_DestroyRuntime">JS_DestroyRuntime</a></code> to clean it up when you're done. When your application is done with SpiderMonkey altogether, use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_ShutDown" title="en/JS_ShutDown">JS_ShutDown</a></code> to free any remaining cached resources. (This is a mere nicety if the process is about to exit anyway. But as that is not always the case, calling <code>JS_Shutdown</code> is a good habit to get into.)</p>
  </li>
  <li>
    <p>The context: Use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewContext" title="en/JS_NewContext">JS_NewContext</a></code> and <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DestroyContext" title="en/JS_DestroyContext">JS_DestroyContext</a></code>. For maximum ECMAScript standard compliance, applications should also use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetOptions" title="en/JS_SetOptions">JS_SetOptions</a></code> to enable <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetOptions" title="en/JS_SetOptions">JSOPTION_VAROBJFIX</a></code>. To get the latest JavaScript language features, applications may use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetVersion" title="en/JS_SetVersion">JS_SetVersion</a></code>. Error reporting is also per-context and is enabled using <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetErrorReporter" title="en/JS_SetErrorReporter">JS_SetErrorReporter</a></code>.</p>
  </li>
  <li>
    <p>The global object: To create this object, you first need a <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSClass" title="en/JSClass">JSClass</a></code> with the <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSClass.flags" title="en/JSClass.flags">JSCLASS_GLOBAL_FLAGS</a></code> option. The example below defines a very basic <code>JSClass</code> (named <code>global_class</code>) with no methods or properties of its own. Use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewGlobalObject" title="en/SpiderMonkey/JSAPI_Reference/JS_NewGlobalObject">JS_NewGlobalObject</a></code> to create a global object. Use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_InitStandardClasses" title="en/JS_InitStandardClasses">JS_InitStandardClasses</a></code> to populate it with the standard JavaScript globals.</p>
  </li>
</ul>
<p>This may seem like a lot of pieces for a simple application. It amounts to about 50 lines of code, as shown below. But the JSAPI is designed to scale to applications that need many threads, many contexts, and many global objects. It is a fine-grained API, supporting many different combinations of the parts, and giving applications precise control over how SpiderMonkey behaves.</p>
<p>Here is the boilerplate code necessary for a minimal JSAPI application. It contains everything described above.</p>
<pre>
/*
 * This define is for Windows only, it is a work-around for bug 661663.
 */
#ifdef _MSC_VER
# define XP_WIN
#endif
#include "jsapi.h"
/* The class of the global object. */
static <a href="/JSAPI_Reference/JSClass" title="JSAPI_Reference/JSClass">JSClass</a> global_class = { "global", <a href="SpiderMonkey/JSAPI_Reference/JSClass.flags" title="SpiderMonkey/JSAPI_Reference/JSClass.flagss">JSCLASS_GLOBAL_FLAGS</a>, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JSCLASS_NO_OPTIONAL_MEMBERS };
/* The error reporter callback. */
void reportError(JSContext *cx, const char *message, <a href="/JSAPI_Reference/JSErrorReport" title="JSAPI_Reference/JSErrorReport">JSErrorReport</a> *report) {
     fprintf(stderr, "%s:%u:%s\n", report-&gt;filename ? report-&gt;filename : "<no filename="">", (unsigned int) report-&gt;lineno, message);

}

int main(int argc, const char *argv[]) {
    /* JS variables. */
    JSRuntime *rt;
    JSContext *cx;
    JSObject *global;
    /* Create a JS runtime. */
    rt = <a href="/JSAPI_Reference/JS_NewRuntime" title="JSAPI_Reference/JS_NewRuntime">JS_NewRuntime</a>(8L * 1024L * 1024L);
    if (rt == NULL)
       return 1;
    /* Create a context. */
    cx = <a href="/JSAPI_Reference/JS_NewContext" title="JSAPI_Reference/JS_NewContext">JS_NewContext</a>(rt, 8192);
    if (cx == NULL)
       return 1;
    <a href="/JSAPI_Reference/JS_SetOptions" title="JSAPI_Reference/JS_SetOptions">JS_SetOptions</a>(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
    <a href="/JSAPI_Reference/JS_SetVersion" title="JSAPI_Reference/JS_SetVersion">JS_SetVersion</a>(cx, JSVERSION_LATEST);
    <a href="/JSAPI_Reference/JS_SetErrorReporter" title="JSAPI_Reference/JS_SetErrorReporter">JS_SetErrorReporter</a>(cx, reportError);
    /* Create the global object in a new compartment. */
    global = <a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewCompartmentAndGlobalObject" title="https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JS_NewCompartmentAndGlobalObject">JS_NewCompartmentAndGlobalObject</a>(cx, &amp;global_class, NULL);
    if (global == NULL)
       return 1;
    /* Populate the global object with the standard globals, like Object and Array. */
    if (!<a href="/JSAPI_Reference/JS_InitStandardClasses" title="JSAPI_Reference/JS_InitStandardClasses">JS_InitStandardClasses</a>(cx, global))
       return 1;

   /* Your application code here. This may include JSAPI calls to create your own custom JS objects and run scripts. */

   <a href="/JSAPI_Reference/JS_DestroyContext" title="JSAPI_Reference/JS_DestroyContext">JS_DestroyContext</a>(cx);
   <a href="/JSAPI_Reference/JS_DestroyRuntime" title="JSAPI_Reference/JS_DestroyRuntime">JS_DestroyRuntime</a>(rt);
   <a href="/JSAPI_Reference/JS_ShutDown" title="JSAPI_Reference/JS_ShutDown">JS_ShutDown</a>();
   return 0;
}
</no></pre>
<p>A typical JSAPI application should also run garbage collection periodically. An application can do this by periodically calling <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_MaybeGC" title="en/JS_MaybeGC">JS_MaybeGC</a></code>.</p>
<p>Multithreaded applications have additional basic requirements, including build requirements. See <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_THREADSAFE" title="en/JS_THREADSAFE">JS_THREADSAFE</a></code>.</p>
<h3 id="Native_functions" name="Native_functions">Native functions</h3>
<p>Much of the rest of this guide explains how to expose custom functionality to scripts. The simplest way to start is by exposing a global native function.</p>
<p>Native functions are implemented in C/C++ but can be called from JavaScript just like any other function. The native function's signature must match <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JSNative" title="En/JSNative"><code>JSNative</code></a>.</p>
<pre>
#include &lt;stdlib.h&gt;
#include &lt;time.h&gt;
#include "jsapi.h"

/* A simple JS wrapper for the rand() function, from the C standard library.
   This example shows how to return a number from a JSNative.
   This is nearly the simplest possible JSNative function. */
JSBool myjs_rand(JSContext *cx, uintN argc, jsval *vp)
{
    JS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL(rand()));
    return JS_TRUE;
}

/* A wrapper for the srand() function, from the C standard library.
   This example shows how to handle optional arguments. */
JSBool myjs_srand(JSContext *cx, uintN argc, jsval *vp)
{
    uint32 seed;

    if (!<a class="internal" href="JSAPI_Reference/JS_ConvertArguments">JS_ConvertArguments</a>(cx, argc, JS_ARGV(cx, vp), "/u", &amp;seed))
        return JS_FALSE;

    /* If called with no arguments, use the current time as the seed. */
    if (argc == 0)
        seed = time(NULL);

    srand(seed);

    JS_SET_RVAL(cx, vp, <a class="internal" href="JSAPI_Reference/JSVAL_VOID">JSVAL_VOID</a>);  /* return undefined */
    return JS_TRUE;
}

/* A wrapper for the system() function, from the C standard library.
   This example shows how to report errors. */
JSBool myjs_system(JSContext *cx, uintN argc, jsval *vp)
{
&nbsp;&nbsp;&nbsp; JSString* str;
    char *cmd;
    int rc;

    if (!<a class="internal" href="JSAPI_Reference/JS_ConvertArguments">JS_ConvertArguments</a>(cx, argc, JS_ARGV(cx, vp), "s", &amp;str))
        return JS_FALSE;

    cmd = JS_EncodeString(cx, str);
    rc = system(cmd);
    JS_free(cx, cmd);
    if (rc != 0) {
        /* Throw a JavaScript exception. */
        <a class="internal" href="JSAPI_Reference/JS_ReportError">JS_ReportError</a>(cx, "Command failed with exit code %d", rc);
        return JS_FALSE;
    }

    JS_SET_RVAL(cx, vp, <a class="internal" href="JSAPI_Reference/JSVAL_VOID">JSVAL_VOID</a>);  /* return undefined */
    return JS_TRUE;
}
</pre>
<p>Each <code>JSNative</code> has the same signature, regardless of what arguments it expects to receive from JavaScript.</p>
<p>The JavaScript arguments to the function are given in <code>argc</code> and <code>vp</code>. <code>argc</code> tells how many actual arguments the caller passed, and <code>JS_ARGV(cx, vp)</code> returns an array of those arguments. The arguments do not have native C/C++ types like <code>int</code> and <code>float</code>; rather, they are <a class="internal" href="/En/SpiderMonkey/JSAPI_Reference/Jsval" title="en/jsval"><code>jsval</code></a>s, JavaScript values. The native function uses <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_ConvertArguments" title="en/JS_ConvertArguments"><code>JS_ConvertArguments</code></a> to convert the arguments to C/C++ types and store them in local variables. The native function uses <code>JS_SET_RVAL(cx, vp, val)</code> to store its JavaScript return value.</p>
<p>On success, a <code>JSNative</code> must call <a href="/en/SpiderMonkey/JSAPI_Reference/JSFastNative" title="en/SpiderMonkey/JSAPI Reference/JS SET RVAL"><code>JS_SET_RVAL</code></a> and return <code>JS_TRUE</code>. The value passed to <code>JS_SET_RVAL</code> is returned to the JavaScript caller.</p>
<p>On failure, a <code>JSNative</code> calls an error-reporting function, in this case <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_ReportError" title="en/JS_ReportError"><code>JS_ReportError</code></a>, and returns <code>JS_FALSE</code>. This causes a JavaScript exception to be thrown. The caller can catch the exception using a JavaScript <code>try/catch</code> statement.</p>
<p>To make native functions callable from JavaScript, declare a table of <a class="internal" href="/En/SpiderMonkey/JSAPI_Reference/JSFunctionSpec" title="en/JSFunctionSpec"><code>JSFunctionSpec</code></a>s describing the functions. Then call <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_DefineFunctions" title="en/JS_DefineFunctions"><code>JS_DefineFunctions</code></a>.</p>
<pre>
static JSFunctionSpec myjs_global_functions[] = {
    <a class="internal" href="../JS_FS">JS_FS</a>("rand",   myjs_rand,   0, 0),
    JS_FS("srand",  myjs_srand,  0, 0),
    JS_FS("system", myjs_system, 1, 0),
    <a class="internal" href="../JS_FS_END">JS_FS_END</a>
};

    ...
    if (!<a class="internal" href="JSAPI_Reference/JS_DefineFunctions">JS_DefineFunctions</a>(cx, global, myjs_global_functions))
        return JS_FALSE;
    ...
</pre>
<p>Once the functions are defined in <code>global</code>, any script that uses <code>global</code> as the global object can call them, just as any web page can call <code>alert</code>. In the environment we have created, the "hello world" script looks like this:</p>
<pre>
system("echo hello world");
</pre>
<h2 id="JSAPI_Concepts">JSAPI Concepts</h2>
<p>This section aims to fill in the major gaps in the picture of the JSAPI&nbsp;presented so far. To do anything useful with SpiderMonkey, you must read all three sections.</p>
<h3 id="Working_with_JS_Values" name="Working_with_JS_Values">JavaScript values</h3>
<p>Main article: <code><a href="/En/SpiderMonkey/JSAPI_Reference/Jsval" title="en/jsval">jsval</a></code></p>
<p>JavaScript is a dynamically typed language: variables and properties do not have a type that is fixed at compile time. How can a statically typed language, like C or C++, in which all variables have types, interact with JavaScript? The JSAPI provides a data type, <code><a href="/En/SpiderMonkey/JSAPI_Reference/Jsval" title="en/jsval">jsval</a></code>, which can contain JavaScript values of any type. A <code>jsval</code> can be a number, a string, a boolean value, a reference to an object (like an <code>Object</code>, <code>Array</code>, <code>Date</code>, or <code>Function</code>), or one of the special values <code>null</code> or <code>undefined</code>.</p>
<p>For integers and boolean values, a <code>jsval</code> contains the value itself. In other cases, the <code>jsval</code> is a pointer to an object, string, or number.</p>
<div class="warning">
  <p><strong>Warning:</strong> Like C/C++ pointers, and unlike JavaScript <code>var</code>s, a <code>jsval</code> is <strong>not</strong> automatically initialized to a safe value, and <strong>can</strong> become a dangling pointer!</p>
  <p>A dangling pointer is a pointer that used to point to a valid object, but no longer does because the object no longer exists. Using a dangling pointer can crash a C/C++ program (or worse). In the case of <code>jsval</code>, the JavaScript garbage collector recycles objects, strings, and numbers that don't appear to be in use, and a <code>jsval</code> by itself does not protect its referent from the garbage collector. See <em>Garbage collection</em> below for crucial information on how to use <code>jsval</code>s safely.</p>
</div>
<p>The JSAPI includes macros that test the JavaScript data type of a <code>jsval</code>. These are:</p>
<ul>
  <li><code><a href="/en/SpiderMonkey/JSAPI_Reference/JSVAL_IS_OBJECT" title="en/JSVAL_IS_OBJECT">JSVAL_IS_OBJECT</a></code></li>
  <li><code><a href="/en/SpiderMonkey/JSAPI_Reference/JSVAL_IS_NUMBER" title="en/JSVAL_IS_NUMBER">JSVAL_IS_NUMBER</a></code></li>
  <li><code><a href="/en/SpiderMonkey/JSAPI_Reference/JSVAL_IS_INT" title="en/JSVAL_IS_INT">JSVAL_IS_INT</a></code></li>
  <li><code><a href="/en/SpiderMonkey/JSAPI_Reference/JSVAL_IS_DOUBLE" title="en/JSVAL_IS_DOUBLE">JSVAL_IS_DOUBLE</a></code></li>
  <li><code><a href="/en/SpiderMonkey/JSAPI_Reference/JSVAL_IS_STRING" title="en/JSVAL_IS_STRING">JSVAL_IS_STRING</a></code></li>
  <li><code><a href="/en/SpiderMonkey/JSAPI_Reference/JSVAL_IS_BOOLEAN" title="en/JSVAL_IS_BOOLEAN">JSVAL_IS_BOOLEAN</a></code></li>
  <li><code><a href="/en/SpiderMonkey/JSAPI_Reference/JSVAL_IS_NULL" title="en/JSVAL_IS_NULL">JSVAL_IS_NULL</a></code></li>
  <li><code><a href="/en/SpiderMonkey/JSAPI_Reference/JSVAL_IS_VOID" title="en/JSVAL_IS_VOID">JSVAL_IS_VOID</a></code></li>
</ul>
<p style="text-align: left;">If a <code>jsval</code> points to a <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSObject" title="en/JSObject">JSObject</a></code>, <code><a href="/en/SpiderMonkey/JSAPI_Reference/jsdouble" title="en/jsdouble">jsdouble</a></code>, or <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSString" title="en/JSString">JSString</a></code>, you can cast the <code>jsval</code> to its underlying data type using <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSVAL_TO_OBJECT" title="en/JSVAL_TO_OBJECT">JSVAL_TO_OBJECT</a></code>, <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSVAL_TO_DOUBLE" title="en/JSVAL_TO_DOUBLE">JSVAL_TO_DOUBLE</a></code>, and <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSVAL_TO_STRING" title="en/JSVAL_TO_STRING">JSVAL_TO_STRING</a></code>, respectively. This is useful in some cases where your application or a JSAPI function requires a variable or argument of a specific data type, rather than a <code>jsval</code>. Similarly, you can cast a <code>JSObject</code>, <code>jsdouble</code>, or <code>JSString</code> pointer to a <code>jsval</code> using <code><a href="/en/SpiderMonkey/JSAPI_Reference/OBJECT_TO_JSVAL" title="en/OBJECT_TO_JSVAL">OBJECT_TO_JSVAL</a></code>, <code><a href="/en/SpiderMonkey/JSAPI_Reference/DOUBLE_TO_JSVAL" title="en/DOUBLE_TO_JSVAL">DOUBLE_TO_JSVAL</a></code>, or <code><a href="/en/SpiderMonkey/JSAPI_Reference/STRING_TO_JSVAL" title="en/STRING_TO_JSVAL">STRING_TO_JSVAL</a></code>.</p>
<h3 id="Garbage_collection">Garbage collection</h3>
<p>As it runs, JavaScript code implicitly allocates memory for objects, strings, variables, and so on.&nbsp; Garbage collection is the process by which the JavaScript engine detects when those pieces of memory are no longer reachable—that is, they could not possibly ever be used again—and reclaims the memory.</p>
<p>Garbage collection has two important consequences for JSAPI applications. First, the application must be very careful to ensure that any values it needs are GC-reachable. The garbage collector is rather eager about its job. Any object you leave lying around will be destroyed if you don't tell the JSAPI you're still using it. Second, the application should take steps to reduce the performance impact of garbage collection.</p>
<h4 id="Keeping_objects_alive">Keeping objects alive</h4>
<p>If your JSAPI application crashes, it is likely due to a GC-related error. The application must ensure that the garbage collector can reach all the objects, numbers, and strings that are still being used. Otherwise, the GC will free the memory occupied by those values, leading to a probable crash the next time your program tries to use them.</p>
<p>There are many ways to ensure that a value is GC-reachable.</p>
<ul>
  <li>If you just need the value to remain reachable for the duration of a <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSNative" title="en/JSNative">JSNative</a></code> call, store it in <code>*rval</code> or an element of the <code>argv</code> array. The values stored in those locations are always reachable. To get extra <code>argv</code> slots, use <code><a href="/En/SpiderMonkey/JSAPI_Reference/JSFunctionSpec" title="en/JSFunctionSpec">JSFunctionSpec</a>.extra</code>.</li>
</ul>
<ul>
  <li>If a custom object needs certain values to remain in memory, just store the values in <a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetProperty" title="en/JS_SetProperty">properties</a> of the object. As long as the object is reachable, its properties will remain reachable. If these values must not be accessible from JavaScript, use <a href="/en/SpiderMonkey/JSAPI_Reference/JS_GetReservedSlot" title="en/JS_GetReservedSlot">reserved slots</a> instead. Or store the values in <a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetPrivate" title="en/JS_SetPrivate">private data</a> and implement <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSClass.mark" title="en/JSClass.mark">JSClass.mark</a></code>.</li>
</ul>
<ul>
  <li>If a function creates new objects, strings, or numbers, it can use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_EnterLocalRootScope" title="en/JS_EnterLocalRootScope">JS_EnterLocalRootScope</a></code> and <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_LeaveLocalRootScope" title="en/JS_LeaveLocalRootScope">JS_LeaveLocalRootScope</a></code> to keep those values alive for the duration of the function.</li>
</ul>
<ul>
  <li>To keep a value alive permanently, store it in a <a href="/en/SpiderMonkey/JSAPI_Reference/JS_AddRoot" title="JS_AddRoot">GC root</a>.</li>
</ul>
<p>Still, GC bugs do occur. These two functions, both available only in <code>DEBUG</code> builds, are especially useful for debugging GC-related crashes:</p>
<ul>
  <li>Use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetGCZeal" title="en/JS_SetGCZeal">JS_SetGCZeal</a></code> to enable extra garbage collection. GC zeal usually causes a GC-related crash to occur much sooner (closer to its cause) and more reliably. It's for development and debugging only, because the extra garbage collection makes JS very slow.</li>
</ul>
<ul>
  <li>Use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DumpHeap" title="en/JS_DumpHeap">JS_DumpHeap</a></code> to dump the SpiderMonkey heap or specific interesting parts of it.</li>
</ul>
<p>See <a href="/en/SpiderMonkey_Garbage_Collection_Tips" title="en/SpiderMonkey_Garbage_Collection_Tips">SpiderMonkey Garbage Collection Tips</a> for more details.</p>
<h4 id="GC_performance">GC performance</h4>
<p>Overly frequent garbage collection can be a performance issue. Some applications can reduce the frequency of garbage collection simply by increasing the initial size of the <code>JSRuntime</code>.</p>
<p>Perhaps the best technique is to perform garbage collection during idle time, when it is least likely to have any impact on the user. By default, the JavaScript engine performs garbage collection when it has no other choice except to grow the process. This means that garbage collection typically happens when memory-intensive code is running, perhaps the worst possible time. An application can trigger garbage collection at a more convenient time by calling <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_GC" title="en/JS_GC">JS_GC</a></code> or <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_MaybeGC" title="en/JS_MaybeGC">JS_MaybeGC</a></code>. <code>JS_GC</code> forces garbage collection. <code>JS_MaybeGC</code> performs garbage collection only if it is likely to reclaim a worthwhile amount of memory.</p>
<h3 id="Errors_and_exceptions">Errors and exceptions</h3>
<p>The importance of checking the return value of JSAPI functions, of course, goes without saying. Almost every JSAPI function that takes a <code><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JSRuntime" title="en/SpiderMonkey/JSAPI Reference/JSRuntime">JSContext</a> *</code> argument can fail. The system might run out of memory. There might be a syntax error in a script. Or a script might explicitly <code>throw</code> an exception.</p>
<p>The JavaScript language has exceptions, and C++ has exceptions, but they are not the same thing. SpiderMonkey does not use C++ exceptions for anything. JSAPI functions never throw C++&nbsp;exceptions, and when SpiderMonkey calls an application callback, the callback must not throw a C++&nbsp;exception.</p>
<h4 id="Throwing_and_catching_exceptions">Throwing and catching exceptions</h4>
<p>We have already seen one example of how to throw an exception from a <code>JSNative</code> function. Simply call <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_ReportError" title="en/SpiderMonkey/JSAPI Reference/JS ReportError"><code>JS_ReportError</code></a>, with <code>printf</code>-style arguments, and return <code>JS_FALSE</code>.</p>
<pre>
    rc = system(cmd);
    if (rc != 0) {
        /* Throw a JavaScript exception. */
        <a class="internal" href="mks://localhost/en/SpiderMonkey/JSAPI_Reference/JS_ReportError" title="en/SpiderMonkey/JSAPI Reference/JS ReportError">JS_ReportError</a>(cx, "Command failed with exit code %d", rc);
        return JS_FALSE;
    }
</pre>
<p>This is very much like the JavaScript statement <code>throw new Error("Command failed with exit code " + rc);</code>. Again, note that calling <code>JS_ReportError</code> does not cause a C++&nbsp;exception to be thrown. It only creates a new JavaScript Error object and stores it in the context as the current <dfn>pending exception</dfn>. The application must also return JS_FALSE.</p>
<p>Once the C/C++ function returns JS_FALSE, the JavaScript engine starts unwinding the JavaScript stack, looking for a <code>catch</code> or <code>finally</code> block to execute. But SpiderMonkey's stack unwinding never removes application's C/C++ functions from the stack. Instead, SpiderMonkey simply returns <code>JS_FALSE</code> or <code>NULL</code> to the application, which can then handle the error as it chooses—or just return <code>JS_FALSE</code> to let it propagate further up the stack.</p>
<p>Several more examples of throwing and catching exceptions can be found in the <a class="internal" href="/En/SpiderMonkey/JSAPI_Cookbook" title="En/SpiderMonkey/JSAPI Phrasebook">JSAPI Phrasebook</a>.</p>
<h4 id="Error_reports">Error reports</h4>
<p>TODO your custom errorreporter</p>
<p>TODO when errors are reported</p>
<h4 id="Automatic_handling_of_uncaught_exceptions">Automatic handling of uncaught exceptions</h4>
<p>The <code>JS_Compile</code>*, <code>JS_Call</code>*, <code>JS_Execute</code>*, and <code>JS_Evaluate</code>* functions automatically pass exceptions to the error reporter in certain cases. Each of these functions checks, just before it returns, to see if an exception is pending in the current <code>JSContext</code>. If so, it then checks to see if there is any other JavaScript script or function on the stack in that <code>JSContext</code>. If so, then the exception might yet be caught, so SpiderMonkey does nothing and returns JS_FALSE, allowing the exception to propagate. But if nothing is on the JavaScript stack, then the uncaught exception is passed to the error reporter and the pending exception is cleared.</p>
<p>The basic consequence is that top-level application code can just set an error reporter and start calling JSAPI&nbsp;functions. It never has to explicitly handle uncaught exceptions; the error reporter is automatically called. An application can disable automatic uncaught-exception handling using the <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_SetOptions" title="en/SpiderMonkey/JSAPI Reference/JS
SetOptions"><code>JSOPTION_DONT_REPORT_UNCAUGHT</code></a> option, but it must then deal with uncaught exceptions explicitly by calling <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_IsExceptionPending" title="en/SpiderMonkey/JSAPI Reference/JS IsExceptionPending"><code>JS_IsExceptionPending</code></a>, <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_GetPendingException" title="en/SpiderMonkey/JSAPI Reference/JS GetPendingException"><code>JS_GetPendingException</code></a>, <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_ReportPendingException" title="en/SpiderMonkey/JSAPI Reference/JS_ReportPendingException"><code>JS_ReportPendingException</code></a>, and/or <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_ClearPendingException" title="en/SpiderMonkey/JSAPI Reference/JS ClearPendingException"><code>JS_ClearPendingException</code></a> whenever a JSAPI&nbsp;function returns <code>JS_FALSE</code>&nbsp;or <code>NULL</code>.</p>
<h4 id="Uncatchable_errors">Uncatchable errors</h4>
<p>Another way for a <code>JSNative</code> callback to report an error is like this:</p>
<pre>
    if (p == NULL) {
        <a class="internal" href="mks://localhost/en/SpiderMonkey/JSAPI_Reference/JS_ReportOutOfMemory" title="en/SpiderMonkey/JSAPI Reference/JS ReportOutOfMemory">JS_ReportOutOfMemory</a>(cx);
        return JS_FALSE;
    }
</pre>
<p>This does something subtly different from what <code>JS_ReportError</code> does.</p>
<p>Most errors, including those raised by <code>JS_ReportError</code>, are represented as JavaScript exceptions and thus interact with the JavaScript exception-handling language features, <code>try</code>, <code>catch</code>, and <code>finally</code>. However, in some cases we do not want scripts to be able to <code>catch</code> an error; we want script execution to terminate right away. If the system runs out of memory in the middle of a script, we do not want <code>finally</code> blocks to execute, because almost anything a script does requires at least a little memory, and we have none. If a script has been running too long and we want to kill it, it's no good to throw an exception—the script could just <code>catch</code> it and keep going.</p>
<p>Therefore <code><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_ReportOutOfMemory" title="en/SpiderMonkey/JSAPI Reference/JS ReportOutOfMemory">JS_ReportOutOfMemory</a>(cx)</code> does <em>not</em> set the pending exception. It is an uncatchable error.</p>
<p>If SpiderMonkey runs out of memory, or a JSAPI callback returns <code>JS_FALSE</code> without an exception pending, this is treated as an uncatchable error. The JavaScript stack is unwound in the normal way except that <code>catch</code> and <code>finally</code> blocks are ignored. The most recent JSAPI call returns <code>JS_FALSE</code> or <code>NULL</code> to the application.</p>
<p>An uncatchable error leaves the <code>JSContext</code> in a good state. It can be used again right away. The application does not have to do anything to “recover” from the error, as far as the JSAPI is concerned. (Of course, if the error is that the system is out of memory, that problem remains to be dealt with.)</p>
<p>Here is some example code that throws an uncatchable error.</p>
<pre>
    /* Call the error reporter, if any. This part is optional. */
    <a class="internal" href="mks://localhost/en/SpiderMonkey/JSAPI_Reference/JS_ReportError" title="en/SpiderMonkey/JSAPI Reference/JS ReportError">JS_ReportError</a>(cx, "The server room is on fire!");
    JS_ReportPendingException(cx);

    /* Make sure the error is uncatchable. */
    <a class="internal" href="mks://localhost/en/SpiderMonkey/JSAPI_Reference/JS_ClearPendingException" title="en/SpiderMonkey/JSAPI Reference/JS ClearPendingException">JS_ClearPendingException</a>(cx);
    return JS_FALSE;
</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 id="More sample code" name="More sample code">More sample code</h2>
<p>The following examples illustrate how to achieve a few different effects using the JSAPI.</p>
<p>Note that the most important example is in the "A minimal example" section above. More JSAPI code samples appear in the <a href="/En/SpiderMonkey/JSAPI_Cookbook" title="en/JSAPI_Phrasebook">JSAPI Phrasebook</a>.</p>
<h3 id="Defining_objects_and_properties">Defining objects and properties</h3>
<pre>
/* Statically initialize a class to make "one-off" objects. */
<a href="JSAPI_Reference/JSClass">JSClass</a> my_class = {
    "MyClass",

    /* All of these can be replaced with the corresponding JS_*Stub
       function pointers. */
    my_addProperty, my_delProperty, my_getProperty, my_setProperty,
    my_enumerate,   my_resolve,     my_convert,     my_finalize
};

<a href="JSAPI_Reference/JSObject">JSObject</a> *obj;

/*
 * Define an object named in the global scope that can be enumerated by
 * for/in loops.  The parent object is passed as the second argument, as
 * with all other API calls that take an object/name pair.  The prototype
 * passed in is null, so the default object prototype will be used.
 */
obj = <a href="JSAPI_Reference/JS_DefineObject">JS_DefineObject</a>(cx, globalObj, "myObject", &amp;my_class, NULL,
                      <a href="JSAPI_Reference/JS_GetPropertyAttributes">JSPROP_ENUMERATE</a>);

/*
 * Define a bunch of properties with a JSPropertySpec array statically
 * initialized and terminated with a null-name entry.  Besides its name,
 * each property has a "tiny" identifier (MY_COLOR, e.g.) that can be used
 * in switch statements (in a common my_getProperty function, for example).
 */
enum my_tinyid {
    MY_COLOR, MY_HEIGHT, MY_WIDTH, MY_FUNNY, MY_ARRAY, MY_RDONLY
};

static <a href="JSAPI_Reference/JSPropertySpec">JSPropertySpec</a> my_props[] = {
    {"color",       MY_COLOR,       JSPROP_ENUMERATE},
    {"height",      MY_HEIGHT,      JSPROP_ENUMERATE},
    {"width",       MY_WIDTH,       JSPROP_ENUMERATE},
    {"funny",       MY_FUNNY,       JSPROP_ENUMERATE},
    {"array",       MY_ARRAY,       JSPROP_ENUMERATE},
    {"rdonly",      MY_RDONLY,      JSPROP_READONLY},
    {0}
};

<a href="JSAPI_Reference/JS_DefineProperties">JS_DefineProperties</a>(cx, obj, my_props);

/*
 * Given the above definitions and call to JS_DefineProperties, obj will
 * need this sort of "getter" method in its class (my_class, above).  See
 * the example for the "It" class in js.c.
 */
static JSBool
my_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    if (<a href="JSAPI_Reference/JSVAL_IS_INT">JSVAL_IS_INT</a>(id)) {
        switch (<a href="JSAPI_Reference/JSVAL_TO_INT">JSVAL_TO_INT</a>(id)) {
          case MY_COLOR:  *vp = . . .; break;
          case MY_HEIGHT: *vp = . . .; break;
          case MY_WIDTH:  *vp = . . .; break;
          case MY_FUNNY:  *vp = . . .; break;
          case MY_ARRAY:  *vp = . . .; break;
          case MY_RDONLY: *vp = . . .; break;
        }
    }
    return JS_TRUE;
}
</pre>
<h3 id="Defining_classes" name="Defining_classes">Defining classes</h3>
<p>This pulls together the above API elements by defining a constructor function, a prototype object, and properties of the prototype and of the constructor, all with one API call.</p>
<p>Initialize a class by defining its constructor function, prototype, and per-instance and per-class properties. The latter are called "static" below by analogy to Java. They are defined in the constructor object's scope, so that <code>MyClass.myStaticProp</code> works along with <code>new MyClass()</code>.</p>
<p><code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_InitClass" title="en/JS_InitClass">JS_InitClass</a></code> takes a lot of arguments, but you can pass <code>NULL</code> for any of the last four if there are no such properties or methods.</p>
<p>Note that you do not need to call <code>JS_InitClass</code> to make a new instance of that class—otherwise there would be a chicken-and-egg problem making the global object—but you should call <code>JS_InitClass</code> if you require a constructor function for script authors to call via <code>new</code>, and/or a class prototype object (<code>MyClass.prototype</code>) for authors to extend with new properties at run time. In general, if you want to support multiple instances that share behavior, use <code>JS_InitClass</code>.</p>
<pre>
protoObj = <a href="JSAPI_Reference/JS_InitClass">JS_InitClass</a>(cx, globalObj, NULL, &amp;my_class,

                        /* native constructor function and min arg count */
                        MyClass, 0,

                        /* prototype object properties and methods -- these
                           will be "inherited" by all instances through
                           delegation up the instance's prototype link. */
                        my_props, my_methods,

                        /* class constructor properties and methods */
                        my_static_props, my_static_methods);
</pre>
<h3 id="Running_scripts" name="Running_scripts">Running scripts</h3>
<pre>
/* These should indicate source location for diagnostics. */
char *filename;
uintN lineno;

/*
 * The return value comes back here -- if it could be a GC thing, you must
 * add it to the GC's "root set" with <a href="JSAPI_Reference/JS_AddRoot">JS_AddRoot</a>(cx, &amp;thing) where thing
 * is a JSString *, JSObject *, or jsdouble *, and remove the root before
 * rval goes out of scope, or when rval is no longer needed.
 */
jsval rval;
JSBool ok;

/*
 * Some example source in a C string.  Larger, non-null-terminated buffers
 * can be used, if you pass the buffer length to JS_EvaluateScript.
 */
char *source = "x * f(y)";

ok = <a href="JSAPI_Reference/JS_EvaluateScript">JS_EvaluateScript</a>(cx, globalObj, source, strlen(source),
                       filename, lineno, &amp;rval);

if (ok) {
    /* Should get a number back from the example source. */
    jsdouble d;

    ok = <a href="JSAPI_Reference/JS_ValueToNumber">JS_ValueToNumber</a>(cx, rval, &amp;d);
    . . .
}
</pre>
<h4 id="Calling_functions" name="Calling_functions">Calling functions</h4>
<pre>
/* Call a global function named "foo" that takes no arguments. */
ok = <a href="JSAPI_Reference/JS_CallFunctionName">JS_CallFunctionName</a>(cx, globalObj, "foo", 0, 0, &amp;rval);

jsval argv[2];

/* Call a function in obj's scope named "method", passing two arguments. */
argv[0] = . . .;
argv[1] = . . .;
ok = <a href="JSAPI_Reference/JS_CallFunctionName">JS_CallFunctionName</a>(cx, obj, "method", 2, argv, &amp;rval);
</pre>
<h3 id="JSContext" name="JSContext">JSContext</h3>
<p>Because there is a certain amount of overhead associated with allocating and maintaining contexts, a JSAPI application should:</p>
<ol>
  <li>Create only as many contexts as it needs at one time.</li>
  <li>Keep contexts for as long as they may be needed, rather than destroying and recreating them as needed.</li>
</ol>
<p>If your application creates multiple runtimes, the application may need to know which runtime a context is associated with. In this case, use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_GetRuntime" title="en/JS_GetRuntime">JS_GetRuntime</a></code>.</p>
<p>Use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_GetContextPrivate" title="en/JS_GetContextPrivate">JS_SetContextPrivate</a></code> and <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_GetContextPrivate" title="en/JS_GetContextPrivate">JS_GetContextPrivate</a></code> to associate application-specific data with a context.</p>
<h3 id="Initializing_built-in_and_global_JS_objects" name="Initializing_built-in_and_global_JS_objects">Initializing built-in and global JS objects</h3>
<p>For a complete list of built-in objects provided by SpiderMonkey, see <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_InitStandardClasses" title="en/JS_InitStandardClasses">JS_InitStandardClasses</a></code>.</p>
<p>The global object that an application provides to scripts largely determines what those scripts can do. For example, the Firefox browser uses its own global object, <code>window</code>. To change the global object for your application, call <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetGlobalObject" title="en/JS_SetGlobalObject">JS_SetGlobalObject</a></code>.</p>
<h3 id="Creating_and_initializing_custom_objects" name="Creating_and_initializing_custom_objects">Creating and initializing custom objects</h3>
<p>In addition to using the engine's built-in objects, you will create, initialize, and use your own JS objects. This is especially true if you are using the JS engine with scripts to automate your application. Custom JS objects can provide direct program services, or they can serve as interfaces to your program's services. For example, a custom JS object that provides direct service might be one that handles all of an application's network access, or might serve as an intermediary broker of database services. Or a JS object that mirrors data and functions that already exist in the application may provide an object-oriented interface to C code that is not otherwise, strictly-speaking, object-oriented itself. Such a custom object acts as an interface to the application itself, passing values from the application to the user, and receiving and processing user input before returning it to the application. Such an object might also be used to provide access control to the underlying functions of the application.</p>
<p>There are two ways to create custom objects that the JS engine can use:</p>
<ul>
  <li>Write a JS script that creates an object, its properties, methods, and constructor, and then pass the script to the JS engine at run time.</li>
  <li>Embed code in your application that defines the object's properties and methods, call the engine to initialize a new object, and then set the object's properties through additional engine calls. An advantage of this method is that your application can contain native methods that directly manipulate the object embedding.</li>
</ul>
<p>In either case, if you create an object and then want it to persist in the run time where it can be used by other scripts, you must root the object by calling <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_AddRoot" title="en/JS_AddRoot">JS_AddRoot</a></code> or <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_AddRoot" title="en/JS_AddRoot">JS_AddNamedRoot</a></code>. Using these functions ensures that the JS engine will keep track of the objects and clean them up during garbage collection, if appropriate.</p>
<h3 id="Creating_an_object_from_a_script" name="Creating_an_object_from_a_script">Creating an object from a script</h3>
<p>One reason to create a custom JS object from a script is when you only need an object to exist as long as the script that uses it is executing. To create objects that persist across script calls, you can embed the object code in your application instead of using a script.</p>
<p><strong>Note</strong>: You can also use scripts to create persistent objects, too.</p>
<p>To create a custom object using a script:</p>
<ol>
  <li>Define and spec the object. What is it intended to do? What are its data members (properties)? What are its methods (functions)? Does it require a run time constructor function?</li>
  <li>Code the JS script that defines and creates the object. For example: function myfun(){ var x = newObject(); . . . } <strong>NOTE</strong>: Object scripting using JavaScript occurs outside the context of embedding the JS engine in your applications. For more information about object scripting, see the <em>Client-Side JavaScript Guide</em> and the <em>Server-Side JavaScript Guide</em>. Embed the appropriate JS engine call(s) in your application to compile and execute the script. You have two choices: 1.) compile and execute a script with a single call to <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_EvaluateScript" title="en/JS_EvaluateScript">JS_EvaluateScript</a></code>, <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_EvaluateScript" title="en/JS_EvaluateScript">JS_EvaluateUCScript</a></code> or 2.) compile the script once with a call to <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileScript" title="en/JS_CompileScript">JS_CompileScript</a></code> or <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileScript" title="en/JS_CompileScript">JS_CompileUCScript</a></code>, and then execute it repeatedly with individual calls to <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_ExecuteScript" title="en/JS_ExecuteScript">JS_ExecuteScript</a></code>. The "UC" versions of these calls provide support for Unicode-encoded scripts.</li>
</ol>
<p>An object you create using a script only can be made available only during the lifetime of the script, or can be created to persist after the script completes execution. Ordinarily, once script execution is complete, its objects are destroyed. In many cases, this behavior is just what your application needs. In other cases, however, you will want object persistence across scripts, or for the lifetime of your application. In these cases you need to embed object creation code directly in your application, or you need to tie the object directly to the global object so that it persists as long as the global object itself persists.</p>
<h3 id="Custom_objects" name="Custom_objects">Custom objects</h3>
<p>An application can create a custom object without bothering with a <code>JSClass</code>:</p>
<ol>
  <li>Implement the getters, setters, and methods for your custom object in C or C++.&nbsp; Write a <a class="internal" href="/En/SpiderMonkey/JSAPI_Reference/JSPropertyOp" title="en/JSPropertyOp"><code>JSPropertyOp</code></a> for each getter or setter.&nbsp; Write a <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JSNative" title="En/JSNative"><code>JSNative</code></a> or <code>JSFastNative</code> for each method.</li>
  <li>Declare a <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSPropertySpec" title="en/JSPropertySpec">JSPropertySpec</a></code> array containing information about your custom object's properties, including getters and setters.</li>
  <li>Declare a <code><a href="/En/SpiderMonkey/JSAPI_Reference/JSFunctionSpec" title="en/JSFunctionSpec">JSFunctionSpec</a></code> array containing information about your custom object's methods.</li>
  <li>Call <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewObject" title="en/JS_NewObject">JS_NewObject</a></code>, <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_ConstructObject" title="en/JS_ConstructObject">JS_ConstructObject</a></code>, or <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DefineObject" title="en/JS_DefineObject">JS_DefineObject</a></code> to create the object.</li>
  <li>Call <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DefineProperties" title="en/JS_DefineProperties">JS_DefineProperties</a></code> to define the object's properties.</li>
  <li>Call <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DefineFunctions" title="en/JS_DefineFunctions">JS_DefineFunctions</a></code> to define the object's methods.</li>
</ol>
<p><code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetProperty" title="en/JS_SetProperty">JS_SetProperty</a></code> can also be used to create properties on an object. The properties it creates do not have getters or setters; they are ordinary JavaScript properties.</p>
<h3 id="Providing_private_data_for_objects" name="Providing_private_data_for_objects">Providing private data for objects</h3>
<p>Like contexts, you can associate large quantities of data with an object without having to store the data in the object itself. Call <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetPrivate" title="en/JS_SetPrivate">JS_SetPrivate</a></code> to establish a pointer to private data for the object, and call <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_GetPrivate" title="en/JS_GetPrivate">JS_GetPrivate</a></code> to retrieve the pointer so that you can access the data. Your application is responsible for creating and managing this optional private data.</p>
<p>To create private data and associate it with an object:</p>
<ol>
  <li>Establish the private data as you would a normal C void pointer variable.</li>
  <li>Call <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetPrivate" title="en/JS_SetPrivate">JS_SetPrivate</a></code>, specify the object for which to establish private data, and specify the pointer to the data.</li>
</ol>
<p>For example:</p>
<pre>
 JS_SetPrivate(cx, obj, pdata);
</pre>
<p>To retrieve the data at a later time, call <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_GetPrivate" title="en/JS_GetPrivate">JS_GetPrivate</a></code>, and pass the object as an argument. This function returns the pointer to an object's private data:</p>
<pre>
 pdata = JS_GetPrivate(cx, obj);
</pre>
<h2 id="Special_topics">Special topics</h2>
<h3 id="Handling_Unicode" name="Handling_Unicode">Unicode</h3>
<p>To pass Unicode data between JavaScript and native code, represent the data in UTF-16 in memory. JavaScript strings, property names, and programs are all made up of <code>jschar</code>s, which are 16-bit unsigned integers.</p>
<p>Many JSAPI functions operate on null-terminated, 8-bit <code>char</code> strings. These functions convert their <code>char *</code> arguments to 16-bit strings by zero-extending each 8-bit <code>char</code> to 16 bits—unless <a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_C_STRINGS_ARE_UTF8" title="en/SpiderMonkey/JSAPI Reference/JS C STRINGS ARE UTF8"><code>JS_C_STRINGS_ARE_UTF8</code></a> is defined or <a class="internal" href="/En/SpiderMonkey/JSAPI_Reference/JS_CStringsAreUTF8" title="en/SpiderMonkey/JSAPI Reference/JS SetCStringsAreUTF8"><code>JS_SetCStringsAreUTF8</code></a> has been called, in which case each <code>char *</code> string is interpreted as UTF-8 Unicode text.</p>
<p>The JSAPI provides <code>jschar</code>-based versions of many API functions that operate on strings, object properties, and JavaScript code.</p>
<table class="fullwidth-table">
  <thead>
    <tr>
      <th><code>char</code>-based function</th>
      <th><code>jschar</code>-based function</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td colspan="2"><em>Unicode data</em></td>
    </tr>
    <tr>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_GetStringBytes" title="En/SpiderMonkey/JSAPI Reference/JS GetStringBytes">JS_GetStringBytes</a><span class="internal"> {{obsolete_inline("js1.8.5")}}</span></td>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_GetStringChars" title="en/SpiderMonkey/JSAPI Reference/JS GetStringChars">JS_GetStringChars</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewString" title="en/JS_NewString">JS_NewString</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewString" title="en/JS_NewString">JS_NewUCString</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewStringCopyN" title="en/JS_NewStringCopyN">JS_NewStringCopyN</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewStringCopyN" title="en/JS_NewStringCopyN">JS_NewUCStringCopyN</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewStringCopyZ" title="en/JS_NewStringCopyZ">JS_NewStringCopyZ</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewStringCopyZ" title="en/JS_NewStringCopyZ">JS_NewUCStringCopyZ</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_InternString" title="en/JS_InternString">JS_InternString</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_InternString" title="en/JS_InternString">JS_InternUCString</a>, <a href="/en/SpiderMonkey/JSAPI_Reference/JS_InternString" title="en/JS_InternString">JS_InternUCStringN</a></td>
    </tr>
    <tr>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_ReportErrorNumber" title="En/SpiderMonkey/JSAPI Reference/JS ReportErrorNumber">JS_ReportErrorNumber</a></td>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_ReportErrorNumber" title="en/SpiderMonkey/JSAPI Reference/JS ReportErrorNumberUC">JS_ReportErrorNumberUC</a></td>
    </tr>
    <tr>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_ReportErrorNumber" title="En/SpiderMonkey/JSAPI Reference/JS ReportErrorNumber">JS_ReportErrorFlagsAndNumber</a></td>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_ReportErrorNumber" title="En/SpiderMonkey/JSAPI Reference/JS ReportErrorNumber">JS_ReportErrorFlagsAndNumberUC</a></td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <td colspan="2"><em>Unicode property names</em></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DefineProperty" title="en/JS_DefineProperty">JS_DefineProperty</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DefineProperty" title="en/JS_DefineProperty">JS_DefineUCProperty</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DefinePropertyWithTinyId" title="en/JS_DefinePropertyWithTinyId">JS_DefinePropertyWithTinyId</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DefinePropertyWithTinyId" title="en/JS_DefinePropertyWithTinyId">JS_DefineUCPropertyWithTinyId</a></td>
    </tr>
    <tr>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_DefineFunction" title="En/SpiderMonkey/JSAPI Reference/JS DefineFunction">JS_DefineFunction</a></td>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_DefineFunction" title="En/SpiderMonkey/JSAPI Reference/JS DefineFunction">JS_DefineUCFunction</a></td>
    </tr>
    <tr>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_HasProperty" title="En/SpiderMonkey/JSAPI Reference/JS HasProperty">JS_HasProperty</a></td>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_HasProperty" title="En/SpiderMonkey/JSAPI Reference/JS HasProperty">JS_HasUCProperty</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_LookupProperty" title="en/JS_LookupProperty">JS_LookupProperty</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_LookupProperty" title="en/JS_LookupProperty">JS_LookupUCProperty</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_GetProperty" title="en/JS_GetProperty">JS_GetProperty</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_GetProperty" title="en/JS_GetProperty">JS_GetUCProperty</a></td>
    </tr>
    <tr>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_GetPropertyAttributes" title="En/SpiderMonkey/JSAPI Reference/JS GetPropertyAttributes">JS_GetPropertyAttributes</a></td>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_GetPropertyAttributes" title="en/SpiderMonkey/JSAPI Reference/JS GetUCPropertyAttributes">JS_GetUCPropertyAttributes</a></td>
    </tr>
    <tr>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_GetPropertyAttrsGetterAndSetter" title="En/SpiderMonkey/JSAPI Reference/JS GetPropertyAttrsGetterAndSetter">JS_GetPropertyAttrsGetterAndSetter</a></td>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_GetPropertyAttrsGetterAndSetter" title="en/SpiderMonkey/JSAPI Reference/JS GetUCPropertyAttrsGetterAndSetter">JS_GetUCPropertyAttrsGetterAndSetter</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetProperty" title="en/JS_SetProperty">JS_SetProperty</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetProperty" title="en/JS_SetProperty">JS_SetUCProperty</a></td>
    </tr>
    <tr>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_SetPropertyAttributes" title="En/SpiderMonkey/JSAPI Reference/JS SetPropertyAttributes">JS_SetPropertyAttributes</a></td>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_SetPropertyAttributes" title="En/SpiderMonkey/JSAPI Reference/JS SetPropertyAttributes">JS_SetUCPropertyAttributes</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DeleteProperty2" title="en/JS_DeleteProperty2">JS_DeleteProperty2</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DeleteProperty2" title="en/JS_DeleteProperty2">JS_DeleteUCProperty2</a></td>
    </tr>
    <tr>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_AlreadyHasOwnProperty" title="En/SpiderMonkey/JSAPI Reference/JS AlreadyHasOwnProperty">JS_AlreadyHasOwnProperty</a></td>
      <td><a class="internal" href="/en/SpiderMonkey/JSAPI_Reference/JS_AlreadyHasOwnProperty" title="En/SpiderMonkey/JSAPI Reference/JS AlreadyHasOwnProperty">JS_AlreadyHasOwnUCProperty</a></td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <td colspan="2"><em>Unicode JavaScript source</em></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileScript" title="en/JS_CompileScript">JS_CompileScript</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileScript" title="en/JS_CompileScript">JS_CompileUCScript</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileScriptForPrincipals" title="en/JS_CompileScriptForPrincipals">JS_CompileScriptForPrincipals</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileScriptForPrincipals" title="en/JS_CompileScriptForPrincipals">JS_CompileUCScriptForPrincipals</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileFunction" title="en/JS_CompileFunction">JS_CompileFunction</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileFunction" title="en/JS_CompileFunction">JS_CompileUCFunction</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileFunctionForPrincipals" title="en/JS_CompileFunctionForPrincipals">JS_CompileFunctionForPrincipals</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileFunctionForPrincipals" title="en/JS_CompileFunctionForPrincipals">JS_CompileUCFunctionForPrincipals</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_EvaluateScript" title="en/JS_EvaluateScript">JS_EvaluateScript</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_EvaluateScript" title="en/JS_EvaluateScript">JS_EvaluateUCScript</a></td>
    </tr>
    <tr>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_EvaluateScriptForPrincipals" title="en/JS_EvaluateScriptForPrincipals">JS_EvaluateScriptForPrincipals</a></td>
      <td><a href="/en/SpiderMonkey/JSAPI_Reference/JS_EvaluateScriptForPrincipals" title="en/JS_EvaluateScriptForPrincipals">JS_EvaluateUCScriptForPrincipals</a></td>
    </tr>
  </tbody>
</table>
<p><code>jschar</code>-based functions work exactly like their <code>char</code>-based namesakes, except that where traditional functions take a <code>char *</code> argument, the Unicode versions take a <code>jschar *</code> argument, usually with a separate argument specifying the length of the string in <code>jschar</code>s.</p>
<h3 id="Compiled_scripts" name="Compiled_scripts">Compiled scripts</h3>
<p>The easiest way to run a script is to use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_EvaluateScript" title="en/JS_EvaluateScript">JS_EvaluateScript</a></code>, which compiles and executes the script in one go.</p>
<p>But sometimes an application needs to run a script many times. In this case, it may be faster to compile the script once and execute it multiple times.</p>
<p>The JSAPI provides a type, <code><a href="/en/JSScript" title="en/JSScript">JSScript</a></code>, that represents a compiled script. The life cycle of a <code>JSScript</code> looks like this:</p>
<ul>
  <li>The application compiles some JavaScript code using <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileScript" title="en/JS_CompileScript">JS_CompileScript</a></code>, <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileFile" title="en/JS_CompileFile">JS_CompileFile</a></code>, or <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileFileHandle" title="en/JS_CompileFileHandle">JS_CompileFileHandle</a></code>. These functions return a pointer to a new <code>JSScript</code>.</li>
</ul>
<ul>
  <li>The application calls <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_ExecuteScript" title="en/JS_ExecuteScript">JS_ExecuteScript</a></code> (or <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_ExecuteScriptPart" title="en/JS_ExecuteScriptPart">JS_ExecuteScriptPart</a></code>) any number of times. It is safe to use a <code>JSScript</code> in multiple different contexts {{ Jsapi_todo("and different global objects?") }}, but only within the <code>JSRuntime</code> and thread in which it was created.</li>
</ul>
<ul>
  <li>The application cleans up the compiled script by calling <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_DestroyScript" title="en/JS_DestroyScript">JS_DestroyScript</a></code>.</li>
</ul>
<p>Here is some example code using a compiled script:</p>
<pre>
/*
 * Compile a script and execute it repeatedly until an
 * error occurs.  (If this ever returns, it returns false.
 * If there's no error it just keeps going.)
 */
<a href="../SpiderMonkey/JSAPI_Reference/JSBool">JSBool</a> compileAndRepeat(<a href="JSAPI_Reference/JSRuntime">JSContext</a> *cx, const char *filename)
{
    <a href="../JSScript">JSScript</a> *script;

    script = <a href="JSAPI_Reference/JS_CompileFile">JS_CompileFile</a>(cx, <a href="JSAPI_Reference/JS_GetGlobalObject">JS_GetGlobalObject</a>(cx), filename);
    if (script == NULL)
        return JS_FALSE;   /* compilation error */

    for (;;) {
        jsval result;

        if (!<a href="JSAPI_Reference/JS_ExecuteScript">JS_ExecuteScript</a>(cx, <a href="JSAPI_Reference/JS_GetGlobalObject">JS_GetGlobalObject</a>(cx), script, &amp;result))
            break;
        <a href="JSAPI_Reference/JS_MaybeGC">JS_MaybeGC</a>(cx);
    }

    <a href="JSAPI_Reference/JS_DestroyScript">JS_DestroyScript</a>(cx, script);
    return JS_FALSE;
}
</pre>
<p>Sometimes it is inconvenient for an application to manage the lifetime of each script. Failing to call <code>JS_DestroyScript</code> can lead to memory leaks, and calling it too soon can cause crashes.</p>
<p>An alternative is to tie the lifetime of the compiled script to the lifetime of a JavaScript object, and let the garbage collector destroy the script when it is no longer reachable. The JSAPI provides this feature via the <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewScriptObject" title="en/JS_NewScriptObject">JS_NewScriptObject</a></code> function. The life cycle of a script using this feature is like this:</p>
<ul>
  <li>The application compiles some JavaScript code.</li>
</ul>
<ul>
  <li>To protect the compiled script from garbage collection, the application creates a <em>compiled script object</em> by calling <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewScriptObject" title="en/JS_NewScriptObject">JS_NewScriptObject</a></code> and makes that object GC-reachable using <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetProperty" title="en/JS_SetProperty">JS_SetProperty</a></code>, <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_GetReservedSlot" title="en/JS_GetReservedSlot">JS_SetReservedSlot</a></code>, <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_AddRoot" title="en/JS_AddRoot">JS_AddRoot</a></code>, or some other function.</li>
</ul>
<ul>
  <li>The application executes the compiled script any number of times.</li>
</ul>
<ul>
  <li>As the application progresses, eventually it doesn't need the compiled script anymore, and the compiled script object becomes unreachable.</li>
</ul>
<ul>
  <li>The garbage collector then eventually collects the unreachable script and its components.</li>
</ul>
<p>Here is example code demonstrating the technique—but note that this case is not really complex enough to warrant the use of <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_NewScriptObject" title="en/JS_NewScriptObject">JS_NewScriptObject</a></code>. The above example does the same thing more directly.</p>
<pre>
/*
 * Compile a script and execute it repeatedly until an
 * error occurs.  (If this ever returns, it returns false.
 * If there's no error it just keeps going.)
 */
<a href="../SpiderMonkey/JSAPI_Reference/JSBool">JSBool</a> compileAndRepeat(<a href="JSAPI_Reference/JSRuntime">JSContext</a> *cx, const char *filename)
{
    <a href="../JSScript">JSScript</a> *script;
    <a href="JSAPI_Reference/JSObject">JSObject</a> *scriptObj;

    script = <a href="JSAPI_Reference/JS_CompileFile">JS_CompileFile</a>(cx, <a href="JSAPI_Reference/JS_GetGlobalObject">JS_GetGlobalObject</a>(cx), filename);
    if (script == NULL)
        return JS_FALSE;   /* compilation error */

    scriptObj = <a href="JSAPI_Reference/JS_NewScriptObject">JS_NewScriptObject</a>(cx, script);
    if (scriptObj == NULL) {
        <a href="JSAPI_Reference/JS_DestroyScript">JS_DestroyScript</a>(cx, script);
        return JS_FALSE;
    }

    if (!<a href="JSAPI_Reference/JS_AddRoot">JS_AddNamedObjectRoot</a>(cx, &amp;scriptObj, "compileAndRepeat script object"))
        return JS_FALSE;

    for (;;) {
        jsval result;

        if (!<a href="JSAPI_Reference/JS_ExecuteScript">JS_ExecuteScript</a>(cx, <a href="JSAPI_Reference/JS_GetGlobalObject">JS_GetGlobalObject</a>(cx), script, &amp;result))
            break;
        <a href="JSAPI_Reference/JS_MaybeGC">JS_MaybeGC</a>(cx);
    }

    <a href="JSAPI_Reference/JS_RemoveRoot">JS_RemoveObjectRoot</a>(cx, &amp;scriptObj);  /* scriptObj becomes unreachable
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and will eventually be collected. */
    return JS_FALSE;
}
</pre>
<h3 id="Security" name="Security">Security</h3>
<p>Many applications use SpiderMonkey to run untrusted code. In designing this kind of application, it's important to think through the security concerns ahead of time. Your application will need to do several things.</p>
<ul>
  <li><strong>Deploy security updates</strong> - Firefox automatically installs updates, so security fixes are deployed as soon as they are available. Unless you also regularly deploy SpiderMonkey security updates, a determined hacker could use publicly known bugs in the engine to attack your application. Note that the kind of attack we're talking about here is where a hacker uses JavaScript to attack the C++ code of the engine itself (or your embedding). The rest of the items in this list talk about security issues that arise within JavaScript itself, even if the engine is working properly.</li>
  <li><strong>Block simple denial-of-service attacks</strong> - A program like <code>while(true){}</code> should not hang your application. To stop execution of scripts that run too long, use <a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetOperationCallback" title="en/SpiderMonkey/JSAPI Reference/JS SetOperationCallback"><code>JS_SetOperationCallback</code></a>. Likewise, a function like <code>function f(){f();}</code> should not crash your application with a stack overflow. To block that, use <a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetNativeStackQuota" title="en/SpiderMonkey/JSAPI Reference/JS SetNativeStackQuota"><code>JS_SetNativeStackQuota</code></a>.</li>
  <li><strong>Control access to sensitive data</strong> - Your application might expose data to some scripts that other scripts should not be able to see. For example, you might let your customers write scripts that operate on their own data, but not other customers' data. These access rules must be enforced somehow.</li>
  <li><strong>Control access to dangerous functionality</strong> - Suppose your application has a method deleteUserAccount() which is meant to be used by administrators only. Obviously if untrusted code can use that method, you have a security problem.</li>
</ul>
<p>The first two problems are important but fairly straightforward and will not be discussed further here. The rest of this section tells how you can control scripts' access to data and functionality.</p>
<h4 id="The_best_security_is_no_security_(really)">The best security is no security (really)</h4>
<p>Do you ever worry about your snake eating your mouse? No? If you don't have both a snake and a mouse, you don't have this problem.</p>
<p>Likewise, if your application doesn't have both untrusted users (snakes) and sensitive data or dangerous functionality that's exposed to JavaScript (mice), then you don't need to read any further. The functions and objects created by <a href="/en/SpiderMonkey/JSAPI_Reference/JS_InitStandardClasses" title="en/SpiderMonkey/JSAPI Reference/JS InitStandardClasses"><code>JS_InitStandardClasses</code></a> are safe. They do not provide access to files, the network, or anything browser-related. The most sensitive information they expose to scripts is the current date and time.</p>
<h4 id="Object-capabilities-based_security">Object-capabilities-based security</h4>
<p>One way to keep a snake from eating a mouse is to keep the mouse and the snake in separate cages.</p>
<p>One way to keep user A from accessing user B's sensitive data or dangerous functions is to keep each user's code in a separate sandbox. That is, create a separate JSContext and global object for each user, and always run each script in the appropriate context. When setting up a new global object, simply don't define any functions the user shouldn't have access to. This approach is called object-capabilities security. To learn more about it, <a class="external" href="http://www.youtube.com/watch?v=EGX2I31OhBE" title="http://www.youtube.com/watch?v=EGX2I31OhBE">watch the movie</a> or <a class="external" href="http://www.erights.org/talks/thesis/">read the book</a>.</p>
<p>The metaphor is misleading in one regard: the snake can't reach the mouse because there's a physical barrier in the way. With SpiderMonkey the situation is more subtle. There's no barrier; there's just no way to get there from here. How can a malicious script get a reference to an object from another sandbox? It might as well be in a parallel universe. Even global variables are per-sandbox. There is no <code>getObjectFromOtherSandbox()</code> function. Your application just needs to take care not to expose any such function to scripts.</p>
<p>In short, never pass one user's data and objects to another user's code, and you'll have no access control issues. SpiderMonkey won't do it if you don't.</p>
<p><strong>Trade-offs.</strong> Object-capabilities security is security without run-time security checks. It is easy to implement, easy to reason about, and fast. But in fairness there are some drawbacks. First, the failure mode is pretty severe. If you do accidentally leak an object from one sandbox into another, the genie is out of the bottle. Once a malicious script gets a reference to a single object in a sandbox, it can use that object to get a reference to the sandbox's global object, and from there, almost any other object or function in that sandbox. There is no way to fix it except to destroy both sandboxes and start over. A second drawback is that the system doesn't automatically respond to <em>changes</em> in user privileges. Suppose user A is not an administrator, so you set up sandbox A with no administrator functionality. If you promote user A to be an admin, SpiderMonkey won't magically update sandbox A to have the administrator classes and functions you didn't define before. Your application will have to do that explicitly. Conversely, if you want to <em>strip</em> user A's administrator privileges, but you have already given administrator functions to user A's scripts, that's even worse. You have no choice but to destroy user A's sandbox and start over.</p>
<h4 id="Fine-grained_security">Fine-grained security</h4>
<p>Another way to keep a snake from eating a mouse is to watch the snake constantly, and if it tries to eat the mouse, intervene.</p>
<p>SpiderMonkey is designed to support custom, application-defined security models. For example, the Firefox browser has a complex and powerful security model. Some JavaScript code ("chrome") has full access to the system. Scripts from web pages ("content") have very limited access. The <a class="external" href="http://www.mozilla.org/projects/security/components/same-origin.html">same origin policy</a> governs a script's access to data and functions from other web pages.</p>
<p>The SpiderMonkey security model is based on the Java principals security model. This model provides a common security interface, but the actual security implementation is up to you.</p>
<p>To use SpiderMonkey's fine-grained security features:</p>
<ul>
  <li>
    <p>Decide what security policy you want to enforce.</p>
  </li>
  <li>
    <p>Insert a call to <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CheckAccess" title="en/JS_CheckAccess">JS_CheckAccess</a></code> at each point in your application where a security check is necessary. (Some security checks are also built into the JavaScript engine; you must decide what security policy to enforce for each of these checks.)</p>
  </li>
  <li>
    <p>Implement one or more <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSPrincipals" title="en/JSPrincipals">JSPrincipals</a></code> objects in your application. You need one <code>JSPrincipals</code> object for each different set of privileges that a script might have.</p>
  </li>
  <li>
    <p>When compiling or executing code, use the JSAPI functions that attach principals to the compiled code. These functions have <code>ForPrincipals</code> in the name. They are listed below. The purpose of using these functions is to ensure that your access check callbacks have accurate information about <em>who</em> is trying to access an object.</p>
    <table class="fullwidth-table" style="width: 839px; height: 166px;">
      <tbody>
        <tr>
          <th>Function</th>
          <th>Purpose</th>
        </tr>
        <tr>
          <td><code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileScriptForPrincipals" title="en/JS_CompileScriptForPrincipals">JS_CompileScriptForPrincipals</a></code>,<br />
            <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileScriptForPrincipals" title="en/JS_CompileScriptForPrincipals">JS_CompileUCScriptForPrincipals</a></code>,<br />
            <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileFileHandle" title="en/JS_CompileFileHandle">JS_CompileFileHandleForPrincipals</a></code></td>
          <td>Compile a script with security information. (To execute a compiled script, use <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_ExecuteScript" title="en/JS_ExecuteScript">JS_ExecuteScript</a></code>.)</td>
        </tr>
        <tr>
          <td><code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileFunctionForPrincipals" title="en/JS_CompileFunctionForPrincipals">JS_CompileFunctionForPrincipals</a></code>,<br />
            <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_CompileFunctionForPrincipals" title="en/JS_CompileFunctionForPrincipals">JS_CompileUCFunctionForPrincipals</a></code></td>
          <td>Create a JavaScript function with security information.</td>
        </tr>
        <tr>
          <td><code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_EvaluateScriptForPrincipals" title="en/JS_EvaluateScriptForPrincipals">JS_EvaluateScriptForPrincipals</a></code>,<br />
            <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_EvaluateScriptForPrincipals" title="en/JS_EvaluateScriptForPrincipals">JS_EvaluateUCScriptForPrincipals</a></code></td>
          <td>Compile and execute a script with security information.</td>
        </tr>
      </tbody>
    </table>
  </li>
  <li>
    <p>Implement access check callback functions (see <code><a href="/en/SpiderMonkey/JSAPI_Reference/JSClass.checkAccess" title="en/JSClass.checkAccess">JSClass.checkAccess</a></code> and <code><a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetCheckObjectAccessCallback" title="en/JS_SetCheckObjectAccessCallback">JS_SetCheckObjectAccessCallback</a></code>). These will be called from <code>JS_CheckAccess</code> and sometimes from within the JavaScript engine. An access check callback function can use jsdbgapi.h functions such as <code><a href="/en/JS_FrameIterator" title="en/JS_FrameIterator">JS_FrameIterator</a></code> and <code><a href="/en/JS_StackFramePrincipals" title="en/JS_StackFramePrincipals">JS_StackFramePrincipals</a></code> to obtain the principals of the code that is trying to perform the checked operation. Then it determines whether to allow the operation to proceed.</p>
  </li>
</ul>
<h3 id="Tracing_and_Profiling">Tracing and Profiling</h3>
<p>There are features provided by&nbsp;the JSAPI&nbsp;that make it easier to implement JavaScript tracers and profilers.</p>
<h4 id="Function_tracing">Function tracing</h4>
<p>If you configure with --enable-trace-jscalls, you can use <a href="/en/SpiderMonkey/JSAPI_Reference/JS_SetFunctionCallback" title="en/SpiderMonkey/JSAPI Reference/JS SetFunctionCallback"><code>JS_SetFunctionCallback()</code></a>&nbsp;to set up a C function to be called whenever a JavaScript function is about to be called, or has finished executing:</p>
<pre class="brush: cpp">
void funcTransition(const JSFunction *func,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const JSScript *scr,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const JSContext *const_cx,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSBool entering)
{
  JSContext *cx = const_cast&lt;JSContext*&gt;(const_cx);
&nbsp; JSString *name = JS_GetFunctionId((JSFunction*)func);
&nbsp; const char *entExit;
&nbsp; const char *nameStr;

&nbsp; /*&nbsp;build a C string for the function's name */

&nbsp; if (!name)&nbsp;{
&nbsp;&nbsp;&nbsp; nameStr = "Unnamed function";
&nbsp; } else {
&nbsp;&nbsp;&nbsp; nameStr = JS_EncodeString(cx, name);
&nbsp; }

&nbsp; /* build a string for whether we're entering or exiting */

&nbsp; if (entering)&nbsp;{
&nbsp;&nbsp;&nbsp; entExit = "Entering";
&nbsp; } else {
&nbsp;&nbsp;&nbsp; entExit = "Exiting";
&nbsp; }

&nbsp; /* output information about the trace */

&nbsp; printf("%s JavaScript function: %s at time:&nbsp;%ld", entExit, nameStr, clock());
} 

void enableTracing(JSContext *cx)&nbsp;{
&nbsp; JS_SetFunctionCallback(cx, funcTransition);
}

void disableTracing(JSContext *cx)&nbsp;{
&nbsp; JS_SetFunctionCallback(cx, NULL);
}
</pre>
Revert to this revision