JSAPI User Guide

  • Revision slug: SpiderMonkey/JSAPI_User_Guide
  • Revision title: JSAPI User Guide
  • Revision id: 42397
  • Created:
  • Creator: Dria
  • Is current revision? No
  • Comment

Revision Content

This document provides an overview of the C language implementation of the JavaScript (JS) engine, and it describes how you can embed engine calls in your applications to make them JS-aware. There are two main reasons for embedding the JS engine in your applications: to automate your applications using scripts; and to use the JS engine and scripts whenever possible to provide cross-platform functionality and eliminate platform-dependent application solutions.

Supported Versions of JavaScript

The JS engine supports JS 1.0 through JS 1.4. JS 1.3 and greater conform to the ECMAScript-262 specification. At its simplest, the JS engine parses, compiles, and executes scripts containing JS statements and functions. The engine handles memory allocation for the JS data types and objects needed to execute scripts, and it cleans up--garbage collects--the data types and objects in memory that it no longer needs.

How Do You Use the Engine?

Generally, you build the JS engine as a shared resource. For example, the engine is a DLL on Windows and Windows NT, and a shared library on Unix. Then you link your application to it, and embed JS engine application programming interface (API) calls in your application. The JS engine's API provides functions that fall into the following broad categories:

  • Data Type Manipulation
  • Run Time Control
  • Class and Object Creation and Maintenance
  • Function and Script Execution
  • String Handling
  • Error Handling
  • Security Control
  • Debugging Support

You will use some of these functional categories, such as run time control and data type manipulation, in every application where you embed JS calls. For example, before you can make any other JS calls, you must create and initialize the JS engine with a call to the JS_NewRuntime function. Other functional catergories, such as security control, provide optional features that you can use as you need them in your applications.

How Does the Engine Relate to Applications?

Conceptually, the JS engine is a shared resource on your system. By embedding engine API calls in your applications you can pass requests to the JS engine for processing. The engine, in turn, processes your requests, and returns values or status information back to your application. Figure 1.1 illustrates this general relationship:

Figure 1.1

Image:Over1.gif

For example, suppose you are using the JS engine to automate your application using JS scripts, and suppose that one script your application runs authenticates a user and sets a user's access rights to the application. First, your application might create a custom JS object that represents a user, including slots for the user's name, ID, access rights, and a potential list of functions that the user has permission to use in the application.

In this case, your application's first request to the JS engine might be a call to JS_NewObject to create the custom object. When the JS engine creates the object, it returns a pointer to your application. Your application can then call the JS engine again to execute scripts that use the object. For example, after creating the user object, your application might immediately pass a script to JS_EvaluateScript for immediate compiling and executing. That script might get and validate a user's information, and then establish the user's access rights to other application features.

In truth, the actual relationship between your application and the JS engine is somewhat more complex than shown in Figure 1.1. For example, it assumes that you have already built the JS engine for your platform. It assumes that your application code includes jsapi.h, and it assumes that the first call your application makes to the engine initializes the JS run time.

When the JS engine receives an initialization request, it allocates memory for the JS run time. Figure 1.2 illustrates this process:

Figure 1.2

Image:Over2.gif

The run time is the space in which the variables, objects, and contexts used by your application are maintained. A context is the script execution state for a thread used by the JS engine. Each simultaneously existent script or thread must have its own context. A single JS run time may contain many contexts, objects, and variables.

Almost all JS engine calls require a context argument, so one of the first things your application must do after creating the run time is call JS_NewContext at least once to create a context. The actual number of contexts you need depends on the number of scripts you expect to use at the same time in your application. You need one context for each simultaneously existing script in your application. On the other hand, if only one script at a time is compiled and executed by your application, then you need only create a single context that you can then reuse for each script.

After you create contexts, you will usually want to initialize the built-in JS objects in the engine by calling JS_InitStandardClasses. The built-in objects include the Array, Boolean, Date, Math, Number, and String objects used in most scripts.

Most applications will also use custom JS objects. These objects are specific to the needs of your applications. They usually represent data structures and methods used to automate parts of your application. To create a custom object, you populate a JS class for the object, call JS_InitClass to set up the class in the run time, and then call JS_NewObject to create an instance of your custom object in the engine. Finally, if your object has properties, you may need to set the default values for them by calling JS_SetProperty for each property.

Even though you pass a specific context to the JS engine when you create an object, an object then exists in the run time independent of the context. Any script can be associated with any context to access any object. Figure 1.3 illustrates the relationship of scripts to the run time, contexts, and objects.

Figure 1.3

Image:Over3.gif

As Figure 1.3 also illustrates, scripts and contexts exist completely independent from one another even though they can access the same objects. Within a given run time, an application can always use any use any unassigned context to access any object. There may be times when you want to ensure that certain contexts and objects are reserved for exclusive use. In these cases, create separate run times for your application: one for shared contexts and objects, and one (or more, depending on your application's needs) for private contexts and objects.

NOTE: Only one thread at a time should be given access to a specific context.

Building the Engine

Before you can use JS in your applications, you must build the JS engine as a shareable library. In most cases, the engine code ships with make files to automate the build process.

For example, under Unix, the js source directory contains a base gnu make file called Makefile.ref, and a config directory. The config directory contains platform-specific .mk files to use with Makefile.ref for your environment. Under Windows NT the nmake file is js.mak.

Always check the source directory for any readme files that may contain late-breaking or updated compilation instructions or information.

What Are the Requirements for Engine Embedding?

To make your application JS-aware, embed the appropriate engine calls in your application code. There are at least five steps to embedding:

  1. Add #include jsapi.h to your C modules to ensure that the compiler knows about possible engine calls. Specialized JS engine work may rarely require you to include additional header files from the JS source code. For example, to include JS debugger calls in your application, code you will need to include jsdbgapi.h in the appropriate modules. Most other header files in the JS source code should not be included. To do so might introduce dependencies based on internal engine implementations that might change from release to release.
  2. Provide support structures and variable declarations in your application. For example, if you plan on passing a script to the JS engine, provide a string variable to hold the text version of the script in your application.Declare structures and variables using the JS data types defined in jsapi.h.
  3. Script application-specific objects using JavaScript. Often these objects will correspond to structures and methods that operate on those structures in your C programs, particularly if you are using the JS engine to automate your application.
  4. Embed the appropriate JS engine API calls and variable references in your application code, including calls to initialize the built-in JS objects, and to create and populate any custom objects your application uses.
  5. Most JS engine calls return a value. If this value is zero or NULL, it usually indicates an error condition. If the value is nonzero, it usually indicates success; in these cases, the return value is often a pointer that your application needs to use or store for future reference. At the very least, your applications should always check the return values from JS engine calls.

The following code fragment illustrates most of these embedding steps, except for the creation of JS scripts, which lies outside the scope of the introductory text. For more information about creating scripts and objects using the JavaScript language itself, see the Client-Side JavaScript Guide. For further information about scripting server-side objects, see the Server-Side JavaScript Guide.

.
.
.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* include the JS engine API header */
#include "jsapi.h"
.
.
.

/* main function sets up global JS variables, including run time,
 * a context, and a global object, then initializes the JS run time,
 * and creates a context. */

int main(int argc, char **argv)
{
  int c, i;
  /*set up global JS variables, including global and custom objects */

  JSVersion version;
  JSRuntime *rt;
  JSContext *cx;
  JSObject  *glob, *it;
  JSBool builtins;

  /* initialize the JS run time, and return result in rt */
  rt = JS_NewRuntime(8L * 1024L * 1024L);

  /* if rt does not have a value, end the program here */
  if (!rt)
    return 1;

  /* create a context and associate it with the JS run time */
  cx = JS_NewContext(rt, 8192);

  /* if cx does not have a value, end the program here */
  if (cx == NULL)
    return 1;

  /* create the global object here */
  glob = JS_NewObject(cx, clasp, NULL, NULL);

  /* initialize the built-in JS objects and the global object */
  builtins = JS_InitStandardClasses(cx, glob);

  .
  . 
  .

  return 0;

}

This example code is simplified to illustrate the key elements necessary to embed JS engine calls in your applications. For a more complete example -- from which these snippets were adapted -- see <cde>js.c</code>, the sample application source code that is included with the JS engine source code.

Understanding Key Embedding Concepts

For most of the JavaScript aware applications you create, you will want to follow some standard JS API embedding practices. The following sections describe the types of API calls you need to embed in all your applications.

In many cases, the order in which you embed certain API calls is important to successful embedding. For example, you must initialize a JS run time before you can make other JS calls. Similarly, you should free the JS run time before you close your application. Therefore, your application's main function typically sandwiches API calls for initializing and freeing the JS run time around whatever other functionality you provide:

int main(int argc, char **argv)
{
  int c, i;

  /*set up global JS variables, including global and custom objects */
  JSVersion version;
  JSRuntime *rt;
  JSContext *cx;
  JSObject  *glob, *it;

  .
  .
  .

  /* initialize the JS run time, and return result in rt */
  rt = JS_NewRuntime(8L * 1024L * 1024L);

  /* if rt does not have a value, end the program here */
  if (!rt)
    return 1;

  .
  .
  .

  /* establish a context */
  cx = JS_NewContext(rt, 8192);

  /* if cx does not have a value, end the program here */
  if (cx == NULL)
    return 1;

  /* initialize the built-in JS objects and the global object */
  builtins = JS_InitStandardClasses(cx, glob);

  .
  .
  .

  /* include your application code here, including JS API calls
   * that may include creating your own custom JS objects. The JS
   * object model starts here. */

  .
  .
  .

  /* Before exiting the application, free the JS run time */
  JS_DestroyRuntime(rt);
As this example illustrates, applications that embed calls to the JS engine are responsible for setting up the JS run time as one of its first acts, and they are responsible for freeing the run time before they exit. In general, the best place to ensure that the run time is initialized and freed is by embedding the necessary calls in whatever module you use as the central JS dispatcher in your application.

After you initialize the run time, you can establish your application's JS object model. The object model determines how your JS objects relate to one another. JS objects are hierarchical in nature. All JS objects are related to the global object by default. They are descendants of the global object. You automatically get a global object when you initialize the standard JS classes:

builtins = JS_InitStandardClasses(cx, glob);

The global object sets up some basic properties and methods that are inherited by all other objects. When you create your own custom objects, they automatically use the properties and methods defined on the global object. You can override these default properties and methods by defining them again on your custom object, or you can accept the default assignments.

You can also create custom objects that are based on other built-in JS objects, or that are based on other custom objects. In each case, the object you create inherits all of the properties and methods of its predecessors in the hierarchical chain, all the way up to the global object. For more information about global and custom objects, see Initializing Built-in and Global JS Objects and Creating and Initializing Custom Objects.

Revision Source

<p>
</p><p>This document provides an overview of the C language implementation of the <a href="en/JavaScript">JavaScript</a> (JS) engine, and it describes how you can embed engine calls in your applications to make them JS-aware. There are two main reasons for embedding the JS engine in your applications: to automate your applications using scripts; and to use the JS engine and scripts whenever possible to provide cross-platform functionality and eliminate platform-dependent application solutions.
</p>
<h3 name="Supported_Versions_of_JavaScript"> Supported Versions of JavaScript </h3>
<p>The JS engine supports JS 1.0 through JS 1.4. JS 1.3 and greater conform to the ECMAScript-262 specification. At its simplest, the JS engine parses, compiles, and executes scripts containing JS statements and functions. The engine handles memory allocation for the JS data types and objects needed to execute scripts, and it cleans up--garbage collects--the data types and objects in memory that it no longer needs.
</p>
<h3 name="How_Do_You_Use_the_Engine.3F"> How Do You Use the Engine? </h3>
<p>Generally, you build the JS engine as a shared resource. For example, the engine is a DLL on Windows and Windows NT, and a shared library on Unix. Then you link your application to it, and embed JS engine application programming interface (API) calls in your application. The JS engine's API provides functions that fall into the following broad categories:
</p>
<ul><li> Data Type Manipulation
</li><li> Run Time Control
</li><li> Class and Object Creation and Maintenance
</li><li> Function and Script Execution
</li><li> String Handling
</li><li> Error Handling
</li><li> Security Control
</li><li> Debugging Support 
</li></ul>
<p>You will use some of these functional categories, such as run time control and data type manipulation, in every application where you embed JS calls. For example, before you can make any other JS calls, you must create and initialize the JS engine with a call to the <code>JS_NewRuntime</code> function. Other functional catergories, such as security control, provide optional features that you can use as you need them in your applications.
</p>
<h3 name="How_Does_the_Engine_Relate_to_Applications.3F"> How Does the Engine Relate to Applications? </h3>
<p>Conceptually, the JS engine is a shared resource on your system. By embedding engine API calls in your applications you can pass requests to the JS engine for processing. The engine, in turn, processes your requests, and returns values or status information back to your application. Figure 1.1 illustrates this general relationship:
</p><p><b><small>Figure 1.1</small></b>
</p><p><img alt="Image:Over1.gif" src="File:en/Media_Gallery/Over1.gif">
</p><p>For example, suppose you are using the JS engine to automate your application using JS scripts, and suppose that one script your application runs authenticates a user and sets a user's access rights to the application. First, your application might create a custom JS object that represents a user, including slots for the user's name, ID, access rights, and a potential list of functions that the user has permission to use in the application.
</p><p>In this case, your application's first request to the JS engine might be a call to <code>JS_NewObject</code> to create the custom object. When the JS engine creates the object, it returns a pointer to your application. Your application can then call the JS engine again to execute scripts that use the object. For example, after creating the user object, your application might immediately pass a script to <code>JS_EvaluateScript</code> for immediate compiling and executing. That script might get and validate a user's information, and then establish the user's access rights to other application features.
</p><p>In truth, the actual relationship between your application and the JS engine is somewhat more complex than shown in Figure 1.1. For example, it assumes that you have already built the JS engine for your platform. It assumes that your application code includes <code>jsapi.h</code>, and it assumes that the first call your application makes to the engine initializes the JS run time.
</p><p>When the JS engine receives an initialization request, it allocates memory for the JS run time. Figure 1.2 illustrates this process:
</p><p><b><small>Figure 1.2</small></b>
</p><p><img alt="Image:Over2.gif" src="File:en/Media_Gallery/Over2.gif">
</p><p>The run time is the space in which the variables, objects, and contexts used by your application are maintained. A context is the script execution state for a thread used by the JS engine. Each simultaneously existent script or thread must have its own context. A single JS run time may contain many contexts, objects, and variables.
</p><p>Almost all JS engine calls require a context argument, so one of the first things your application must do after creating the run time is call <code>JS_NewContext</code> at least once to create a context. The actual number of contexts you need depends on the number of scripts you expect to use at the same time in your application. You need one context for each simultaneously existing script in your application. On the other hand, if only one script at a time is compiled and executed by your application, then you need only create a single context that you can then reuse for each script.
</p><p>After you create contexts, you will usually want to initialize the built-in JS objects in the engine by calling <code>JS_InitStandardClasses</code>. The built-in objects include the <code>Array</code>, <code>Boolean</code>, <code>Date</code>, <code>Math</code>, <code>Number</code>, and <code>String</code> objects used in most scripts.
</p><p>Most applications will also use custom JS objects. These objects are specific to the needs of your applications. They usually represent data structures and methods used to automate parts of your application. To create a custom object, you populate a JS class for the object, call <code>JS_InitClass</code> to set up the class in the run time, and then call <code>JS_NewObject</code> to create an instance of your custom object in the engine. Finally, if your object has properties, you may need to set the default values for them by calling <code>JS_SetProperty</code> for each property.
</p><p>Even though you pass a specific context to the JS engine when you create an object, an object then exists in the run time independent of the context. Any script can be associated with any context to access any object. Figure 1.3 illustrates the relationship of scripts to the run time, contexts, and objects.
</p><p><b><small>Figure 1.3</small></b>
</p><p><img alt="Image:Over3.gif" src="File:en/Media_Gallery/Over3.gif">
</p><p>As Figure 1.3 also illustrates, scripts and contexts exist completely independent from one another even though they can access the same objects. Within a given run time, an application can always use any use any unassigned context to access any object. There may be times when you want to ensure that certain contexts and objects are reserved for exclusive use. In these cases, create separate run times for your application: one for shared contexts and objects, and one (or more, depending on your application's needs) for private contexts and objects.
</p><p><b>NOTE</b>: Only one thread at a time should be given access to a specific context.
</p>
<h3 name="Building_the_Engine"> Building the Engine </h3>
<p>Before you can use JS in your applications, you must build the JS engine as a shareable library. In most cases, the engine code ships with make files to automate the build process.
</p><p>For example, under Unix, the js source directory contains a base gnu make file called <code>Makefile.ref</code>, and a <code>config</code> directory. The <code>config</code> directory contains platform-specific <code>.mk</code> files to use with <code>Makefile.ref</code> for your environment. Under Windows NT the nmake file is <code>js.mak</code>.
</p><p>Always check the source directory for any <code>readme</code> files that may contain late-breaking or updated compilation instructions or information.
</p>
<h3 name="What_Are_the_Requirements_for_Engine_Embedding.3F"> What Are the Requirements for Engine Embedding? </h3>
<p>To make your application JS-aware, embed the appropriate engine calls in your application code. There are at least five steps to embedding:
</p>
<ol>
<li>Add <code>#include jsapi.h</code> to your C modules to ensure that the compiler knows about possible engine calls. Specialized JS engine work may rarely require you to include additional header files from the JS source code. For example, to include JS debugger calls in your application, code you will need to include <code>jsdbgapi.h</code> in the appropriate modules.

Most other header files in the JS source code should <i>not</i> be included. To do so might introduce dependencies based on internal engine implementations that might change from release to release.</li>
<li>Provide support structures and variable declarations in your application. For example, if you plan on passing a script to the JS engine, provide a string variable to hold the text version of the script in your application.Declare structures and variables using the JS data types defined in <code>jsapi.h</code>.</li>
<li>Script application-specific objects using JavaScript. Often these objects will correspond to structures and methods that operate on those structures in your C programs, particularly if you are using the JS engine to automate your application.</li>
<li>Embed the appropriate JS engine API calls and variable references in your application code, including calls to initialize the built-in JS objects, and to create and populate any custom objects your application uses.</li>
<li>Most JS engine calls return a value. If this value is zero or <code>NULL</code>, it usually indicates an error condition. If the value is nonzero, it usually indicates success; in these cases, the return value is often a pointer that your application needs to use or store for future reference. At the very least, your applications should always check the return values from JS engine calls.</li>
</ol>
<p>The following code fragment illustrates most of these embedding steps, except for the creation of JS scripts, which lies outside the scope of the introductory text. For more information about creating scripts and objects using the JavaScript language itself, see the <i>Client-Side JavaScript Guide</i>. For further information about scripting server-side objects, see the <i>Server-Side JavaScript Guide</i>.
</p>
<pre>.
.
.
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

/* include the JS engine API header */
#include "jsapi.h"
.
.
.

/* main function sets up global JS variables, including run time,
 * a context, and a global object, then initializes the JS run time,
 * and creates a context. */

int main(int argc, char **argv)
{
  int c, i;
  /*set up global JS variables, including global and custom objects */

  JSVersion version;
  JSRuntime *rt;
  JSContext *cx;
  JSObject  *glob, *it;
  JSBool builtins;

  /* initialize the JS run time, and return result in rt */
  rt = JS_NewRuntime(8L * 1024L * 1024L);

  /* if rt does not have a value, end the program here */
  if (!rt)
    return 1;

  /* create a context and associate it with the JS run time */
  cx = JS_NewContext(rt, 8192);

  /* if cx does not have a value, end the program here */
  if (cx == NULL)
    return 1;

  /* create the global object here */
  glob = JS_NewObject(cx, clasp, NULL, NULL);

  /* initialize the built-in JS objects and the global object */
  builtins = JS_InitStandardClasses(cx, glob);

  .
  . 
  .

  return 0;

}
</pre>
<p>This example code is simplified to illustrate the key elements necessary to embed JS engine calls in your applications. For a more complete example -- from which these snippets were adapted -- see &lt;cde&gt;js.c&lt;/code&gt;, the sample application source code that is included with the JS engine source code.
</p>
<h3 name="Understanding_Key_Embedding_Concepts"> Understanding Key Embedding Concepts </h3>
<p>For most of the JavaScript aware applications you create, you will want to follow some standard JS API embedding practices. The following sections describe the types of API calls you need to embed in all your applications.
</p><p>In many cases, the order in which you embed certain API calls is important to successful embedding. For example, you must initialize a JS run time before you can make other JS calls. Similarly, you should free the JS run time before you close your application. Therefore, your application's <b>main</b> function typically sandwiches API calls for initializing and freeing the JS run time around whatever other functionality you provide:
</p>
<pre>int main(int argc, char **argv)
{
  int c, i;

  /*set up global JS variables, including global and custom objects */
  JSVersion version;
  JSRuntime *rt;
  JSContext *cx;
  JSObject  *glob, *it;

  .
  .
  .

  /* initialize the JS run time, and return result in rt */
  rt = JS_NewRuntime(8L * 1024L * 1024L);

  /* if rt does not have a value, end the program here */
  if (!rt)
    return 1;

  .
  .
  .

  /* establish a context */
  cx = JS_NewContext(rt, 8192);

  /* if cx does not have a value, end the program here */
  if (cx == NULL)
    return 1;

  /* initialize the built-in JS objects and the global object */
  builtins = JS_InitStandardClasses(cx, glob);

  .
  .
  .

  /* include your application code here, including JS API calls
   * that may include creating your own custom JS objects. The JS
   * object model starts here. */

  .
  .
  .

  /* Before exiting the application, free the JS run time */
  JS_DestroyRuntime(rt);
</pre>
<pre class="eval">As this example illustrates, applications that embed calls to the JS engine are responsible for setting up the JS run time as one of its first acts, and they are responsible for freeing the run time before they exit. In general, the best place to ensure that the run time is initialized and freed is by embedding the necessary calls in whatever module you use as the central JS dispatcher in your application.
</pre>
<p>After you initialize the run time, you can establish your application's JS object model. The object model determines how your JS objects relate to one another. JS objects are hierarchical in nature. All JS objects are related to the global object by default. They are descendants of the global object. You automatically get a global object when you initialize the standard JS classes:
</p>
<pre class="eval">builtins = JS_InitStandardClasses(cx, glob);
</pre>
<p>The global object sets up some basic properties and methods that are inherited by all other objects. When you create your own custom objects, they automatically use the properties and methods defined on the global object. You can override these default properties and methods by defining them again on your custom object, or you can accept the default assignments.
</p><p>You can also create custom objects that are based on other built-in JS objects, or that are based on other custom objects. In each case, the object you create inherits all of the properties and methods of its predecessors in the hierarchical chain, all the way up to the global object. For more information about global and custom objects, see <a href="#Initializing_Built-in_and_Global_JS_Objects">Initializing Built-in and Global JS Objects</a> and <a href="#Creating_and_Initializing_Custom_Objects">Creating and Initializing Custom Objects</a>.
</p>
Revert to this revision