Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use JavaScript engine SpiderMonkey

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article is about how to use the JavaScript engine SpiderMonkey. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

JavaScript is an object scripting language developed by Netscape. It is characterized by simple development and flexible functions. It has been widely used in WEB pages and server applications. HTML itself is static and does not allow users to intervene, but scripts written in JavaScript can be run on the user's browser and interact with the user to achieve dynamic pages. You can associate JavaScript with events (such as mouse clicks, movements, and so on) of most objects embedded in WEB, and then handle these events in your own way. JavaScript provides a wealth of built-in functions and commands, which can display HTML, numerical calculation, multimedia playback, hyperlinks and simple interactive windows in the browser. It can also change the nature of small Java applications running in the browser and easily change the behavior of controls or other objects without in-depth study of its own structure.

Although JavaScript is developed for Internet, its application is not limited to Internet. In fact, it has a wide range of application because of its object-oriented characteristics. As long as our application has a good object mechanism, we can borrow JavaScript to achieve good interactive functions.

SpiderMonkey is a JavaScript engine operated by C language, which supports JS1.4 and ECMAScript-262 specifications. The engine analyzes, compiles and executes scripts to allocate and free memory according to the needs of JS data types and objects. Using this engine, you can make your application have the ability to interpret JavaScript scripts. at present, several projects have adopted SpiderMonkey engine, such as KRV 3D, WebCrossing, WebMerger and so on. KMel 3D is a 3D modeling and simulation system implemented in C++, which has an embedded SpiderMonkey engine to provide custom scripts (scripts created by users to generate complex shapes that are as repetitive as gears) and to drive an interactive teaching system (users can use a JS script program to record their interactions, such as moving the mouse, selecting menus, clicking the mouse, etc.). WebCrossing uses SpiderMonkey to implement a server-side scripting environment, providing a complete Web-server scripting environment. Server-side implementation allows you to create permanent objects in a built-in, object-oriented database, so you can expand the server environment according to your own needs.

Finally, a simple example of how to use SpiderMonkey in your application is given.

How to use the engine

The JS engine is generally used as a shared library, and the application calls the API function provided by the engine. Engine API functions are roughly divided into the following categories: data type manipulation, RunTime control, class and object creation and maintenance, function and script execution, string manipulation, error handling, security control, and Debug support. In general, you only need to use certain types of functions in your application. For example, you must call the JS_NewRuntime function to create and initialize the JS engine before making a JS call. Some types of functions, such as security control classes, provide optional features.

Conceptually, the JS engine is a shared resource on your system. By embedding the engine API call into the application (including the jsapi.h file), you can request the JS engine to operate. Next, the engine processes your request and returns the result or status information to your application.

For example, suppose you are automating an application using the JS engine, and the script application authenticates users and sets permissions. First, the application creates a JS object that describes the user information, including name, ID, permissions, and a list of available functions. In this case, the application first calls JS_NewObject to create the object. When the JS engine creates the object, it returns a pointer to the application. The application then invokes the JS engine to execute the script. After the user object is created, the application immediately passes the script to JS_EvaluateScript to compile and run. The script may obtain and validate the user's information, and then establish the user's access rights.

After receiving the initialization request, the JS engine allocates memory to the JS RunTime, and the variables, objects, and context (context) used by the application are all stored in the RunTime. One context is the execution state of the script (used by the JS engine). Each simultaneous script or thread must have its own context. A single JS RunTime can contain multiple contexts, objects, and variables. Almost all JS engine calls require a context variable, and the application should first call JS_NewContext at least once to create a context after creating the RunTime. The actual number of contexts depends on the number of scripts used at the same time in the program. Every simultaneous script in the program requires a context. On the other hand, if there is only one script to compile and run at a time, you only need a context for each script to reuse.

After creating the context, you call the built-in JS objects in the JS_InitStandardClasses initialization engine, including Array, Boolean, Date, Math, Number, and String. Even if a specific context is passed to the JS engine when the object is created, the object is context-independent in RunTime. Any script can be associated with any context in order to access any object. Scripts and contexts are completely independent of each other, even if they access the same object. In a given RunTime, an application can access any object with an unspecified context. You can create a separate RunTime, one for sharing contexts and objects and the rest for private contexts and objects. Note, however, that only one thread can access a particular context at a time.

To enable the application to recognize JS, embed the appropriate engine calls into your program. There are roughly the following aspects:

Jsapi.h is included in the program.

Structure and variable declarations are provided in the program. For example, if you plan to pass a script to the JS engine, provide a script string variable. Declare variables using the JS data type defined in jsapi.h.

Use JavaScript's script to apply the object. Usually these objects correspond to the structures and methods in C programs.

Insert JS engine API function calls and variable references into the program, including initializing built-in JS objects and creating and configuring user-defined objects.

Most JS engine calls return a value. If the value is NULL, it generally indicates that an error has occurred. If it is not NULL, it indicates success, and the return value is usually a pointer, which the program needs to use or save for future use. The application should check the return value of the JS engine call.

For an application to interpret JavaScript, you must follow certain JS API embedding habits. The following example briefly illustrates some API calling functions that need to be embedded in your application. In most cases, the order in which these functions are inserted is important. For example, the JS RunTime must be initialized before calling another JS API, and the JS RunTime must be released before terminating the program.

# include # include # include / * contains the API header file of the JS engine * / # include "jsapi.h". / / the main program declares global JS variables, including RunTime, a Context, and a global object, then initializes JS RunTime and creates a Context. Int main (int argc, char * * argv) {int c, I; / * declare global JS variables, including global and custom objects * / JSVersion version; JSRuntime * rt; JSContext * cx; JSObject * glob, * it; JSBool builtins; / * initialize JS RunTime and return the result to rt * / rt = JS_NewRuntime (8L * 1024L * 1024L); / * if rt is empty, the program terminates * / if (! rt) return 1 / * create a Context and associate it with JS RunTime * / cx = JS_NewContext (rt, 8192); / * if cx is empty, the program terminates * / if (cx = = NULL) return 1; / * create a global object * / glob = JS_NewObject (cx, clasp, NULL, NULL); / * instantiate built-in objects and global objects * / builtins = JS_InitStandardClasses (cx, glob);. . . Return 0;}

As shown in the example above, the application that calls the JS engine must first create the JS RunTime and release the RunTime before terminating the program. After you instantiate RunTime, you can create your own JS object model. The object model determines the relationship between JS objects, and JS objects are essentially a hierarchical structure. By default, all JS objects are associated with global objects, and they are descendants of global objects. When you initialize the standard JS class, you automatically get a global object:

Builtins = JS_InitStandardClasses (cx, glob)

This global object creates some basic properties and methods that are inherited by other objects. When you create custom objects, they automatically use the properties and methods defined by the global object. You can redefine these properties and methods on custom objects to override these default properties and methods. Of course, you can also accept these default assignments. You can create your own objects based on built-in JS objects or other custom objects. In either case, the object you create inherits all the properties and methods of the parent object in the hierarchical chain, all the way up to the global object.

Go back to the top of the page

Manage RunTime

JS RunTime is the memory space that the JS engine uses to manage context, objects, and variables related to JS functions and scripts. Before executing a JS function or script, you first call JS_NewRunTime to initialize a RunTime. The JS_NewRunTime function takes an unsigned integer parameter that specifies the maximum number of bytes allocated to RunTime memory before the fragment is collected. For example:

Rt = JS_NewRuntime (8L * 1024L * 1024L)

As shown above, JS_NewRuntime returns a pointer to RunTime. Non-NULL indicates that the creation is successful.

Normally, a program needs only one RunTime. Of course, it is also possible to create multiple RunTime as needed and save them on different pointers.

JS_DestroyRuntime (rt)

If you have created multiple RunTime, be sure to destroy each one before the application terminates.

Go back to the top of the page

Administrative context (Contexts)

Almost all JS API calls require you to pass a context parameter. In the JavaScript engine, a context represents a script, and the engine passes context information to the thread running the script. Each script that runs at the same time must be assigned a unique context. When a script is finished, its context is no longer useful, so the context can be reassigned to a new script or released.

Call the function JS_NewContext to create a new context for a script. This function takes two arguments: a RunTime pointer associated with the context and the number of bytes of stack space allocated to the context. If the call is successful, the function returns a pointer to the newly created context. For example:

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

This RunTime must already exist. The stack space you assign to the context must be large enough to provide variables and objects created by scripts that use that context. Note that because you need some overhead related to allocation and maintenance context, you have to do this: in the application, you must determine the number of contexts created as needed; make sure that the context exists when it is needed by the application, rather than repeatedly destroying it and recreating it when needed.

When a context is no longer needed, it should be destroyed and memory resources should be released for use by other programs. Depending on the scope of JS use in the application, it can be destroyed in time after use, or retained and reused until the application terminates. In either case, the function JS_DestroyContext is called to release the context when it is no longer needed, which takes a pointer parameter that points to the context to be released:

JS_DestroyContext (cx)

If your application has created more than one RunTime, the application may need to know which RunTime a context is associated with. In this case, you can call the function JS_GetRuntime, passing the context as an argument. JS_GetRuntime returns a pointer to the appropriate RunTime, if any:

Rt=JS_GetRuntime (cx)

When you create a context, you assign stack space to it to hold variables and objects. You can also store a large amount of data in a given context. However, you must minimize the stack space you need. Call the JS_SetContextPrivate function to create a pointer to the private data needed for the context, and call the JS_GetContextPrivate function to get the pointer so that you can access the data. Your application is responsible for creating and managing private data.

To create private data and associate it with context: first, create private data, the regular C language void* variable; then, call the JS_SetContextPrivate function and specify the context in which the private data is created and a pointer to that data. For example:

JS_SetContextPrivate (cx,pdata)

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

Pdata=JS_GetContextPrivate (cx)

Go back to the top of the page

The handling of objects

1. Create built-in objects and global JS objects

The JavaScript engine provides several built-in objects to simplify your development tasks. For example, built-in array (Array) objects make it easy to create and manipulate array structures in the JS engine. Similarly, the Date object provides a uniform mechanism for manipulating dates. For all the support for built-in objects, see JS_InitStandardClasses. The JS engine uses functions and global objects all the time. Typically, global objects reside behind the scenes, providing default scope for other JS objects and global variables created and used in the application. Before creating your own object, you must initialize the global object. The function object makes the object have the function of and calling the constructor.

A simple API call, JS_InitStandardClasses, initializes global and function objects, and built-in engine objects, making it easy for applications to use them:

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

The JS_InitStandardClasses function returns a JS Boolean value indicating whether the initialization was successful or not.

You can also specify a different global object for the application. For example, Navigator uses window as its global object. To change the application's global object, call JS_SetGlobalObject. For more information, see JS_SetGlobalObject.

2. Create and initialize custom objects

In addition to using engine built-in objects, you can also create, initialize, and use your own JS objects. This is especially true if you are using the JS engine to automate applications with scripts. Custom JS objects can provide direct program services or serve as interfaces to your program services.

There are two ways to create custom objects that can be used by the JS engine:

Write a JS script that creates an object, property, method, and constructor, and then passes the script to the JS engine.

Insert the code into your application, which defines the properties and methods of the object, calls the engine to initialize a new object, and then sets the properties of the object through additional engine calls. The advantage of this approach is that the application can contain local methods for manipulating objects.

In either case, if you create an object and let it exist in the RunTime used by other scripts, you can call JS_AddRef and JS_AddNamedRoot to make the object root. Use these functions to ensure that the JS engine can track these objects and clear them when fragments are collected.

3. How to embed custom objects into an application

It is useful to insert custom objects into the application, for example, when the object is constantly needed, or if you know that there are multiple scripts that need to use one object. The steps to insert a custom object into an application are:

Create a JSPropertySpec data type and assign the property information of the object to it, including the GET and PUT method names of the properties.

Create a JSFunctionSpec data type and assign it the method information used by your object.

Create actual C functions that are executed in response to your object method calls.

Call the JS_NewObject and JS_ConstructObject functions to instantiate the object.

The method that calls the JS_DefineFunctions function to create the object.

Call the JS_DefineProperties function to create the properties of the object.

Code that describes persistent, custom JS objects must be placed near the beginning of program execution, before those that depend on pre-existing objects.

4. Provide private data to the object

Like context, you can associate a large amount of data with an object instead of storing it directly in the object. Call the JS_SetPrivate function to create a pointer to the object's private data, and call the JS_GetPrivate function to get the pointer so that you can access the data. Your application is responsible for creating and managing this private data.

The way to create private data and associate it with an object:

1) create private data as the void* variable of the C language. 2) call the JS_SetPrivate function to specify the object and private data pointer.

For example:

JS_SetContextPrivate (cx,obj,pdata)

Then, to get the data, call the JS_GetPrivate function, passing the object as a parameter. This function returns a pointer to the object's private data:

Pdata=JS_GetContextPrivate (cx,obj)

Go back to the top of the page

Data processing.

1. Dealing with JS data types

JavaScript defines its own data types. Some data types directly correspond to copies in the C language. Others, such as JSObject, jsdouble and JSString, are unique to JavaScript.

In general, you can declare and use JS data types in your application like standard C data types, and the JS engine maintains a separate stack for variables of JS data types that require more than one word storage space, such as JSObject, jsdouble, and JSString. The engine periodically checks these variables to see if they are still in use, and if not, the engine collects them in fragments to free up storage space.

2. Deal with JS values

In addition to the JS data type, the JS engine also uses the JS value, which is called jsvals. A jsval is essentially a pointer to JS data types other than integers. For integers, a jsval contains the value itself. In other cases, the pointer is encoded to contain additional information. Use jsvals to improve the efficiency of the engine, allowing API functions to handle a large number of potential data types. The engine API contains a set of macros to test the JS data type of an jsval. They are:

JSVAL_IS_OBJECT

JSVAL_IS_NUMBER

JSVAL_IS_INT

JSVAL_IS_DOUBLE

JSVAL_IS_STRING

JSVAL_IS_BOOLEAN

In addition to testing an jsval's potential data type, you can also test it to see if it is the original JS data type (JSVAL_IS_PRIMITIVE). The original data types are undefined, null, boolean, numeric, and string.

You can also test whether the value jsval points to is NULL (JSVAL_IS_NULL) or void (JSVAL_IS_VOID).

If a jsval points to a JS data type such as JSObject, jsdouble, or jsstr, you can use JSVAL_TO_OBJECT, JSVAL_TO_DOUBLE, and JSVAL_TO_STRING to convert jsval to its potential type.

3. Deal with JS strings

Many of the things you do in JavaScript involve strings. The JS engine implements a string data type called JSString and a pointer type to an array of JS characters, jschar, using classes to handle Unicode-encoded strings. This engine also implements a set of general Unicode string programs. Finally, the JS engine also provides support for built-in strings, where two or more independent strings can share a string in memory. For strings of type JSString, the engine tracks and manages string resources.

In general, when you use the JS engine to manipulate strings, you should use JS API string handlers to create and copy strings. There is a string manager to create a string at the end of a NULL or a string of a specified length. At the same time, there are programs to calculate the length of strings and compare strings.

4. Support for Unicode and Interned strings

Like other API calls, the name of the Unicode-capable API string function corresponds to the name of the standard engine API string function. For example, if a standard function is named JS_NewStringCopyN, the corresponding Unicode version function is JS_NewUCStringCopN. API string functions with Unicode processing capabilities are also feasible for interned strings.

To save space, the JS engine provides support for sharing a single string instance. This shared string is called "interned strings". Use interned strings when you know in advance that a specific text string will be created in the program and you want to use it multiple times.

The engine provides several calls to the interned string:

JS_InternString, used to create or use a JSString again.

JS_InternUCString, used to create or re-use a JSString of type Unicode.

JS_InternUCStringN, used to create or reuse a fixed-length Unicode-type JSString.

5. Safety control

A security-enhanced API function has been added to the JavaScript1.3,JS engine to compile and run scripts or functions passed to the engine. The JS security model is based on the Java security model. This model provides a general security interface, but the specific security implementation is done by the application itself.

A common scenario used by security mechanisms in applications that can support JavaScript is to compare the authenticity of scripts or to limit the interactivity of scripts. For example, you can compare the code bases of two or more scripts in an application, allowing only scripts from the same code base to modify the script properties of the shared code base.

If you want to implement secure JS, follow these steps:

1) declare the structure of one or more JSPrincipals types in the program.

2) implement the function that will provide security information to the array. These functions include providing an principals array to your application and a mechanism for adding and subtracting references to JS objects with a given set of rules.

3) assign a value to the JSPrincipals structure with your security information, which can include general code information.

4) compile and execute all scripts and functions in the runtime environment. These API functions and their purpose are listed below:

JS_CompileScriptForPrincipals: compiles but does not execute a script with security capabilities.

JS_CompileUCScriptForPrincipals: compiles but does not execute a secure, Unicode-encoded script.

JS_CompileFunctionForPrincipals: use a text string to create a secure JS function.

JS_CompileUCFunctionForPrincipals: use a Unicode-encoded text string to create a JS function with security information.

JS_EvaluateScriptForPrincipals: compile and execute a script with security capabilities.

JS_EvaluateUCScriptForPrincipals: compiles and executes a secure script encoded in Unicode.

Go back to the top of the page

Sample program

The following is a simple sample program that reads a script from the file test.js, then interprets the execution and outputs the result. The People,People object that can be embedded in the script has properties name (representing the person's name), address (representing the person's address), and method print (displaying the person's name and address information on the screen).

For example: the following is a simple js script that first uses the print method to output the person's name and address, then changes the name and address to John and Beijing, respectively, and finally outputs his name and address again to see if the modification is correct.

People.print ()

People.name= "John"

People.address= "Beijing"

People.print ()

The following is the C source code.

# include "js.h" enum tagMY_PEOPLE {MY_NAME,MY_ADDRESS}; static JSBool GetPeopleProperty (JSContext * cx, JSObject * obj, jsval id, jsval * vp); static JSBool SetPeopleProperty (JSContext * cx, JSObject * obj, jsval id, jsval * vp); static JSBool PeoplePrint (JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval); typedef struct {char name [16]; char addr [64];} PeopleInfo;static PeopleInfo milainfoo = {"myName", "myAddress"} / * GETTER*/static JSBool GetPeopleProperty (JSContext * cx, JSObject * obj, jsval id, jsval * vp) {if (JSVAL_IS_INT (id)) {switch (JSVAL_TO_INT (id)) {case MY_NAME: * vp=STRING_TO_JSVAL (JS_NewStringCopyZ (cx,m_ainfo.name)); break Case MY_ADDRESS: * vp=STRING_TO_JSVAL (JS_NewStringCopyZ (cx,m_ainfo.addr)); break;}} return JS_TRUE } / * SETTER*/static JSBool SetPeopleProperty (JSContext * cx, JSObject * obj, jsval id, jsval * vp) {if (JSVAL_IS_INT (id)) {switch (JSVAL_TO_INT (id)) {case MY_NAME: strncpy (m_ainfo.name, JS_GetStringBytes (jss), 15); break Case MY_ADDRESS: strncpy (m_ainfo.addr, JS_GetStringBytes (jss), 63); break;}} return JS_TRUE } / * define print method * / static JSBool PeoplePrint (JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval) {fprintf (stdout, "My Name is% s.\ nMy Addr is% s.\ n", return JS_TRUE; void main () {JSString* jss; char buf [5120]; int len; jsval rval; JSRuntime * rt; JSContext * cx; JSObject * globalObj,*PeopleObj) JSClass global_class = {"global", 0, JS_PropertyStub,JS_PropertyStub, JS_PropertyStub,JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,JS_ConvertStub, JS_FinalizeStub}; / * define the attribute array of the People class * / static JSPropertySpec PeopleProperties [] = {{"name", MY_NAME, JSPROP_ENUMERATE}, {"address", MY_ADDRESS, JSPROP_ENUMERATE}, {0}} / * define the method array of People class * / static JSFunctionSpec PeopleMethods [] = {{"print", PeoplePrint, 0}, {0}}; / * define People class * / static JSClass PeopleClass = {"people", 0, JS_PropertyStub,JS_PropertyStub, GetPeopleProperty, SetPeopleProperty, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub} Typedef struct {} / * initializes JS RunTime and returns the result to rt * / rt = JS_Init (1000000L); if (! rt) return; / * creates a context and associates it with JS RunTime * / cx = JS_NewContext (rt, 5120); if (! cx) return; / * create global object * / if (! (globalObj = JS_NewObject (cx, & global_class, NULL, NULL)) return / * instantiate built-in objects and global objects * / JS_InitStandardClasses (cx, globalObj); / * instantiate People objects * / PeopleObj = JS_DefineObject (cx, globalObj, "People", & PeopleClass, 0pr JSPROPendENUMERATE); / * create properties of objects * / JS_DefineProperties (cx,PeopleObj, PeopleProperties); / * methods to create objects * / JS_DefineFunctions (cx,PeopleObj, PeopleMethods); FILE* fp / * Open the file and read in the script * / if (! (fp = fopen ("test.js", "r")) return; len = fread (buf, 1, 5120, fp); fclose (fp); if (len)

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report