JavaScript C Engine Embedder's Guide

공헌자 숫자: 3명

이 문서는 C로 구현된 JavaScript 엔진인 SpiderMonkey를 전반적으로 소개하며, 애플리케이션이 JavaScript를 인식하도록 하기 위해 어떻게 엔진을 내장하는지에 대해 설명합니다. JavaScript엔진을 여러분의 애플리케이션에 내장하는데는 두가지 큰 이유가 있을 것입니다. 먼저, 스크립트를 사용하여 애플리케이션을 자동화하는 것이 있고, JavaScript엔진과 스크립트를 사용하여 특정 플랫폼에 의존적인 애플케이션 솔루션이 되지 않도록 크로스 플랫폼을 지원하는 것입니다.

지원되는 자바스크립트 버전

모질라 JS 엔진은 JS1.8, JS 1.3을 통해 JS1.0을 지원하고 ECMAScript-262 규약을 충족합니다. 간단하게 보면, JS 엔진은 JS 문장과 함수를 포함하는 스크립트를 파싱하여 컴파일하고 실행합니다. 해당 엔진은 스크립트 실행에 필요한 JS 개체의 메모리 할당을 관리하고 더 이상 필요하지 않을 경우, 가비지 컬렉션을 통해 개체를 지웁니다.

자바스크립트 엔진을 어떻게 사용하나?

일반적으로 JS엔진은 공유 리소스로 빌드합니다. 예를 들어, 윈도와 윈도NT에서는 DLL이고 유닉스에서는 공유 라이브러리가 됩니다. 사용방법은 간단합니다. 우선 애플리케이션에 JS엔진을 링크하고 나서 JS엔진 API를 애플리케이션에 임베딩합니다. 이렇게 하면 JS엔진 API는 다음 종류에 해당하는 기능을 제공하게 됩니다.

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

애플리케이션이 자바스크립트 호출을 지원하려면 런타임 제어(runtime control)와 데이터 타입 조정(datatype manipulation)등과 같은 종류의 기능을 사용합니다. 예를 들어, 어떤 자바스크립트를 호출하기전에 JS_NewRuntime함수를 호출해서 JS엔진을 생성하고 초기화해야 하며, 보안 제어(security control)와 같은 기능은 필요에 따라 선택적으로 사용할 수 있습니다.

How Does the Engine Relate to Applications?

개념적으로 JS엔진은 시스템에 존재하는 공유 리소스라고 볼 수 있습니다. API call을 애플리케이션에 임베딩하여, JS엔진에 요청을 넘길 수 있습니다. 요청을 처리한 엔진은 값이나 상태정보를 애플리케이션에 되돌려줍니다. 그림1.1은 이러한 일반적인 관계를 보여주고 있습니다.

그림 1.1


예를 들어 여러분이 자바스크립트를 사용하여 애플리케이션을 자동화하기 위해 JS엔진을 사용한다고 가정합시다. 그리고 해당 애플리케이션에서 실행하는 스크립트에 사용자를 인증하고 애플리케이션에 사용자 접근 권한을 설정한다고 합시다. 우선, 애플리케이션은 사용자에게 이름, 아이디, 접근권한을 위한 입력과 사용자에게 허락되어 애플리케이션에서 사용 가능한 기능 리스트를 보여줄 수 있는 JS 오브젝트를 생성할 수도 있습니다.

이러한 경우, 애플리케이션이 처음으로 JS엔진에 요청하는 것은 JS_NewObject를 호출하여 사용자 정의 개체를 생성하는 것입니다. JS엔진이 개체를 생성할 때, 애플리케이션에 해당 포인터를 반환합니다. 이때 부터 애플리케이션은 해당 개체를 사용하여 스크립트를 실행하기 위해 다시 JS엔진을 호출할 수 있습니다. 예를 들어, 사용자 개체를 생성한 이후, 애플리케이션은 스크립트를 즉시 컴파일하고 실행하기 위해 바로 JS_EvaluateScript에 전달할 것입니다. 그 결과, 좀 전의 스크립트는 사용자 정보를 얻어 확인해주고 애플리케이션이 가진 다른 기능을 사용할 수 있도록 접근 권한을 허락하게 됩니다.

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


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


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 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 js.c, 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 */

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.

Managing a Run Time

The JS run time is the memory space the JS engine uses to manage the contexts, objects, and variables associated with JS functions and scripts. Before you can execute any JS functions or scripts you must first initialize a run time. The API call that initializes the run time is JS_NewRuntime. JS_NewRuntime takes a single argument, an unsigned integer that specifies the maximum number of bytes of memory to allocate to the run time before garbage collection occurs. For example:

 rt = JS_NewRuntime(8L * 1024L * 1024L);

As this example illustrates, JS_NewRuntime also returns a single value, a pointer to the run time it creates. A non-NULL return value indicates successful creation of the run time.

Normally, you only need one run time for an application. It is possible, however, to create multiple run times by calling JS_NewRuntime as necessary and storing the return value in a different pointer.

When the JS run time is no longer needed, it should be destroyed to free its memory resources for other application uses. Depending on the scope of JS use in your application, you may choose to destroy the run time immediately after its use, or, more likely, you may choose to keep the run time available until your application is ready to terminate. In either case, use the JS_DestroyRuntime to free the run time when it is no longer needed. This function takes a single argument, the pointer to the run time to destroy:


If you use multiple run times, be sure to free each of them before ending your application.

Managing Contexts

Almost all JS API calls require you to pass a context as an argument. A context identifies a script in the JavaScript engine. The engine passes context information to the thread that runs the script. Each simultaneously-executing script must be assigned a unique context. When a script completes execution, its context is no longer in use, so the context can be reassigned to a new script, or it can be freed.

To create a new context for a script, use JS_NewContext. This function takes two arguments: a pointer to the run time with which to associate this context, and the number of bytes of stack space to allocate for the context. If successful, the function returns a pointer to the newly established context. For example:

 JSContext *cx;
 cx = JS_NewContext(rt, 8192);

The run time must already exist. The stack size you specify for the context should be large enough to accommodate any variables or objects created by the script that uses the context. Note that because there is a certain amount of overhead associated with allocating and maintaining contexts you will want to:

  1. Create only as many contexts as you need at one time in your application.
  2. Keep contexts for as long as they may be needed in your application rather than destroying and recreating them as needed.

When a context is no longer needed, it should be destroyed to free its memory resources for other application uses. Depending on the scope of JS use in your application, you may choose to destroy the context immediately after its use, or, more likely, you may choose to keep the context available for reuse until your application is ready to terminate. In either case, use the JS_DestroyContext to free the context when it is no longer needed. This function takes a single argument, the pointer to the context to destroy:


If your application creates multiple run times, the application may need to know which run time a context is associated with. In this case, call JS_GetRuntime, and pass the context as an argument. JS_GetRuntime returns a pointer to the appropriate run time if there is one:

 rt = JS_GetRuntime(cx);

When you create a context, you assign it stack space for the variables and objects that get created by scripts that use the context. You can also store large amounts of data for use with a given context, yet minimize the amount of stack space you need. Call JS_SetContextPrivate to establish a pointer to private data for use with the context, and call JS_GetContextPrivate 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 a context:

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

For example:

 JS_SetContextPrivate(cx, pdata);

To retrieve the data at a later time, call JS_GetContextPrivate, and pass the context as an argument. This function returns the pointer to the private data:

 pdata = JS_GetContextPrivate(cx);

Initializing Built-in and Global JS Objects

The JavaScript engine provides several built-in objects that simplify some of your development tasks. For example, the built-in Array object makes it easy for you to create and manipulate array structures in the JS engine. Similarly, the Date object provides a uniform mechanism for working with and handling dates. For a complete list of built-in objects supported in the engine, see the reference entry for JS_InitStandardClasses.

The JS engine always uses function and global objects. In general, the global object resides behind the scenes, providing a default scope for all other JS objects and global variables you create and use in your applications. Before you can create your own objects, you will want to initialize the global object. The function object enables objects to have and call constructors.

A single API call, JS_InitStandardClasses, initializes the global and function objects and the built-in engine objects so that your application can use them:

 JSBool builtins;
 builtins = JS_InitStandardClasses(cx, glob);

JS_InitStandardClasses returns a JS boolean value that indicates the success or failure of the initialization.

You can specify a different global object for your application. For example, the Netscape Navigator uses its own global object, window. To change the global object for you application, call JS_SetGlobalObject. For more information, see the reference entry for 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.

Embedding a Custom Object in an Application

Embedding a custom JS object in an application is useful when object persistence is required or when you know that you want an object to be available to several scripts. For example, a custom object that represents a user's ID and access rights may be needed during the entire lifetime of the application. It saves overhead and time to create and populate this object once, instead of recreating it over and over again with a script each time the user's ID or permissions need to be checked.

One way to embed a custom object in an application is to:

  1. Create a JSPropertySpec data type, and populate it with the property information for your object, including the name of the property's get and set methods.
  2. Create a JSFunctionSpec data type, and populate it with information about the methods used by your object.
  3. Create the actual C functions that are executed in response to your object's method calls.
  4. Call to JS_NewObject or JS_ConstructObject to instantiate the object.
  5. Call JS_DefineFunctions to create the object's methods.
  6. Call JS_DefineProperties to create the object's properties.

The code that describes persistent, custom JS objects should be placed near the start of application execution, before any code that relies upon the prior existence of the object. Embedded engine calls that instantiate and populate the custom object should also appear before any code that relies on the prior existence of the object.

NOTE: An alternate, and in many cases, easier way to create a custom object in application code is to call JS_DefineObject to create the object, and then make repeated calls to JS_SetProperty to set the object's properties. For more information about defining an object, see JS_DefineObject . For more information about setting an object's properties, see JS_SetProperty.

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);

Handling Unicode

The JS engine now provides Unicode-enabled versions of many API functions that handle scripts, including JS functions. These functions permit you to pass Unicode-encoded scripts directly to the engine for compilation and execution. The following table lists standard engine functions and their Unicode equivalents:

Standard Function Unicode-enabled Function
JS_DefineProperty JS_DefineUCProperty
JS_DefinePropertyWithTinyId JS_DefineUCPropertyWithTinyId
JS_LookupProperty JS_LookupUCProperty
JS_GetProperty JS_GetUCProperty
JS_SetProperty JS_SetUCProperty
JS_DeleteProperty2 JS_DeleteUCProperty2
JS_CompileScript JS_CompileUCScript
JS_CompileScriptForPrincipals JS_CompileUCScriptForPrincipals
JS_CompileFunction JS_CompileUCFunction
JS_CompileFunctionForPrincipals JS_CompileUCFunctionForPrincipals
JS_EvaluateScript JS_EvaluateUCScript
JS_EvaluateScriptForPrincipals JS_EvaluateUCScriptForPrincipals
JS_NewString JS_NewUCString
JS_NewStringCopyN JS_NewUCStringCopyN
JS_NewStringCopyZ JS_NewUCStringCopyZ
JS_InternString JS_InternUCString
-- JS_InternUCStringN

Unicode-enabled functions work exactly like their traditional namesakes, except that where traditional functions take a char * argument, the Unicode versions take a jschar * argument.

Working with JS Data Types

JavaScript defines its own data types. Some of these data types correspond directly to their C counterparts. Others, such as JSObject, jsdouble, and JSString, are specific to JavaScript.

Generally, you declare and use JS data types in your application just as you do standard C data types. The JS engine, however, keeps separate track of JS data type variables that require more than a word of storage: JSObject, jsdouble, and JSString. Periodically, the engine examines these variables to see if they are still in use, and if they are not, it garbage collects them, freeing the storage space for reuse.

Garbage collection makes effective reuse of the heap, but overly frequent garbage collection may be a performance issue. You can control the approximate frequency of garbage collection based on the size of the JS run time you allocate for your application in relation to the number of JS variables and objects your application uses. If your application creates and uses many JS objects and variables, you may want to allocate a sufficiently large run time to reduce the likelihood of frequent garbage collection.

NOTE: Your application can also call JS_GC or JS_MaybeGC to force garbage collection at any time. JS_GC forces garbage collection. JS_MaybeGC performs conditional garbage collection only if a certain percentage of space initially allocated to the run time is in use at the time you invoke the function.

Working with JS Values

In addition to JS data types, the JS engine also uses JS values, called jsvals. A jsval is essentially a pointer to any JS data type except integers. For integers, a jsval contains the integer value itself. In other cases, the pointer is encoded to contain additional information about the type of data to which it points. Using jsvals improves engine efficiency, and permits many API functions to handle a variety of underlying data types.

The engine API contains a group of macros that test the JS data type of a jsval. These are:

Besides testing a jsval for its underlying data type, you can test it to determine if it is a primitive JS data type (JSVAL_IS_PRIMITIVE). Primitives are values that are undefined, null, boolean, numeric, or string types.

You can also test the value pointed to by a jsval to see if it is NULL (JSVAL_IS_NULL) or void (JSVAL_IS_VOID).

If a jsval points to a JS data type of JSObject, jsdouble, or jsstr, 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 JS engine call requires a variable or argument of a specific data type, rather than a jsval. Similarly, you can convert a JSObject, jsdouble, and jsstr to a jsval using OBJECT_TO_JSVAL, DOUBLE_TO_JSVAL, and STRING_TO_JSVAL, respectively.

Unicode String Support

As with other API calls, the names of Unicode-enabled API string functions correspond one-for-one with the standard engine API string function names as follows: if a standard function name is JS_NewStringCopyN, the corresponding Unicode version of the function is JS_NewUCStringCopyN. Unicode-enabled API string functions are also available for interned string.

Interned String Support

To save storage space, the JS engine provides support for sharing a single instance of a string among separate invocations. Such shared strings are called "interned strings". Use interned strings when you know that a particular, string of text will be created and used more than once in an application.

The engine API offers several calls for working with interned strings:

Managing Security

With JavaScript 1.3, the JS engine added security-enhanced API functions for compiling and evaluating scripts and functions passed to the engine. The JS 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.

One common way that security is used in a JavaScript-enabled application is to compare script origins and perhaps limit script interactions. For example, you might compare the codebase of two or more scripts in an application and only allow scripts from the same codebase to modify properties of scripts that share codebases.

To implement secure JS, follow these steps:

  1. Declare one or more structs of type JSPrincipals in your application code.
  2. Implement the functions that will provide security information to the array. These include functions that provide an array of principals for your application, and mechanisms for incrementing and decrementing a reference count on the number of JS objects using a given set of principles.
  3. Populate the JSPrincipals struct with your security information. This information can include common codebase information.
  4. At run time, compile and evaluate all scripts and functions for which you intend to apply security using the JS API calls that require you to pass in a JSPrincipals struct. The following table lists these API functions and their purposes:
Function Purpose
JS_CompileScriptForPrincipals Compiles, but does not execute, a security-enabled script.
JS_CompileUCScriptForPrincipals Compiles, but does not execute, a security-enabled, Unicode-encoded script.
JS_CompileFunctionForPrincipals Creates a security-enabled JS function from a text string.
JS_CompileUCFunctionForPrincipals Creates a JS function with security information from a Unicode-encoded character string.
JS_EvaluateScriptForPrincipals Compiles and executes a security-enabled script.
JS_EvaluateUCScriptForPrincipals Compiles and executes a security-enabled, Unicode-encoded character script.


문서 태그 및 공헌자

Contributors to this page: teoli, Comayjlee, Joone
최종 변경: teoli,