Powerful JavaScript Engine-spidermonkey

Source: Internet
Author: User
Tags glob types of functions
Javascript is widely used in browsers. In fact, JavaScript technology can also be used in non-browser applications, so that the application has an automatic Script Function. This article introduces a very powerful JavaScript Engine spidermonkey. This engine is the JavaScript engine of Mozilla Browser. The engine interface is clearly defined and modularized. This article briefly introduces the basic structure of spidermonkey, explains how to use this engine in your own applications, and finally provides a sample program. This program can explain and execute JavaScript scripts to complete simple script functions.

Javascript is an object scripting language developed by Netscape. It features simple development and flexible functions. It is widely used in web pages and server applications. HTML itself is static and does not allow user intervention. However, script programs written in javascript can run on the user's browser and interact with the user to implement dynamic pages. Javascript can be associated with events (such as mouse clicks and movement) of most objects embedded in the Web, and then processed in your own way. Javascript provides rich built-in functions and commands to display HTML, numeric computing, multimedia playback, hyperlinks, and simple interactive windows in a browser, it can also change the nature of the small Java application running in the browser so that it is easy to change the behavior of controls or other objects without having to study its own structure in depth.

Although Javascript is developed for the Internet, its applications are not limited to the Internet. In fact, it is widely used due to its object-oriented feature, as long as our applications have a good object mechanism, we can use JavaScript to achieve good interaction.

Spidermonkey is a JavaScript engine operated by C language that supports js1.4 and ECMAScript-262 specifications. The engine analyzes, compiles, and executes scripts, and allocates and releases memory based on JS data types and object requirements. Using this engine can give your applications the ability to interpret JavaScript scripts. Currently, several projects have adopted spidermonkey engines, such as K-3D, webcrossing, and webmerger. K-3D is a 3D modeling and simulation system implemented by C ++. The system is embedded with the spidermonkey engine to provide custom scripts (the user creates scripts to generate complex shapes with repeated features like gears ), it can also be used to drive an Interactive Teaching System (you can use a JS script program to record the interaction process, such as moving the mouse, selecting the menu, and clicking the mouse ). Webcrossing uses spidermonkey to implement the server script environment and provides a complete Web-server script environment. The server implementation allows you to create permanent objects in a built-in and object-oriented database, in this way, you can expand the server environment as needed.

The following describes how to use spidermonkey in your application. A simple example program is provided.

How to use the engine

The JS engine is generally used as a shared library, and applications call the API functions provided by the engine. Engine API functions are roughly divided into the following types: data type operations, runtime control, class and object creation and maintenance, function and script execution, string operations, error processing, security control, and debug support. Generally, you only need to use a certain number of functions in your application. For example, before calling JS, you must call the js_newruntime function to create and initialize the JS engine. Some types of functions, such as security control, provide selectable features.

In terms of concept, the JS engine is a shared resource on your system. By embedding engine API calls into applications (including jsapi. H files), you can request the JS engine to perform operations. Next, the engine processes your request and returns the result or status information to your application.

For example, assume that you are using the JS engine to automate applications. The script application identifies users and sets permissions. First, the application creates a JS object that describes user information, including the name, ID, permission, and list of available functions. In this case, the application first calls js_newobject to create an object. After the JS engine creates an object, a pointer is returned to the application. The application then calls the JS engine to execute the script. After a user object is created, the application immediately passes the script to js_evaluatescript for compilation and running. The script may obtain and verify the user information, and then establish the user access right.

After receiving the initialization request, the JS engine allocates memory to the JS runtime. the variables, objects, and context (context) used by the application are stored in the runtime. A context is the execution status of the script (used by the JS engine ). Each concurrent 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. After an application creates a runtime, it must call js_newcontext at least once to create a context. The actual number of contexts depends on the number of scripts simultaneously used in the program. Each script in the program must have a context. On the other hand, if only one script is compiled and run at a time point, you only need one context to reuse each script.

After creating the context, 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 an object is created, this object is also independent of the context in the runtime. Any script can be connected to any context to access any object. Scripts and contexts are completely independent from each other, even if they access the same object. In a given runtime, an application can access any object with unspecified context. You can create an independent runtime for sharing context and object, while others for private context and object. However, note that only one thread can access a specific context at a certain time point. Let the application recognize JS and embed appropriate engine calls into your program. There are roughly the following aspects:

  1. The program contains jsapi. h.
  2. The program provides structure and variable declaration. 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.
  3. Use JavaScript scripts to apply objects. Usually these objects correspond to the structures and methods in C Programs.
  4. Insert API function calls and variable references of the JS engine into the program, including initializing built-in JS objects, creating and configuring user-defined objects.
  5. Most JS engine calls return a value. If the value is null, an error occurs. If it is not null, it indicates success. The returned value is generally a pointer, and the program needs to be used or left for future use. Applications should check the return values of JS engine calls.

To allow applications to interpret JavaScript, you must follow some js api embedding habits. The following example briefly describes some API call functions that need to be embedded in your application. In most cases, the insertion sequence of these functions is very important. For example, you must initialize JS runtime before calling other JS APIs, and release JS runtime before terminating the program.

# Include <stdio. h> # include <stdlib. h> # include <string. h>/* contains the JS engine's API header file */# include "jsapi. H "... // The main program declares global JS variables, including runtime, context, and a global object, initializes JS runtime, and creates a context. Int main (INT argc, char ** argv) {int C, I;/* declares 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, terminate the Program */If (! RT) return 1;/* create a context and associate it with JS runtime */Cx = js_newcontext (RT, 8192);/* If CX is empty, program termination */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 preceding example, the application that calls the JS engine must first create a JS runtime and release the runtime before terminating the program. After the runtime is instantiated, you can create your own JS object model. The object model determines the relationship between JS objects. js objects are essentially a hierarchical structure. By default, all JS objects are associated with global objects, and they are all descendants of global objects. When you initialize a standard JS class, you automatically get a global object:

Builtins = js_initstandardclasses (CX, glob );

This global object creates some basic properties and methods inherited by other objects. When you create custom objects, they automatically use the properties and methods defined by global objects. You can redefine these properties and methods on custom objects to overload these default properties and methods. Of course, you can also accept these default distributions. 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 hierarchy chain and the global object.



Back to Top

Manage Runtime

JS Runtime is the memory space. The JS engine uses it to manage context, objects, and variables related to JS functions and scripts. Before executing a JS function or script, call js_newruntime to initialize a runtime. The js_newruntime function carries an unsigned integer parameter, which specifies the maximum number of bytes allocated to the runtime memory before fragment collection. 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.

Under normal circumstances, a program only needs one runtime. Of course, you can also create multiple runtimes as needed and save them on different pointers.

Js_destroyruntime (RT );

If you have created multiple runtimes, you must destroy each of them before the application is terminated.



Back to Top

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 transmits context information to the thread running the script. Each script running at the same time must be assigned a unique context. After a script is run, its context is no longer useful. Therefore, the context can be assigned to a new script or released.

Call the js_newcontext function to create a new context for a script. This function requires two parameters: a runtime pointer related to the context, and the number of stack space bytes allocated to the context. If the call succeeds, the function returns a pointer pointing to the new 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 it to the variables and objects created by the script that uses the context. Note that some overhead related to the allocation and maintenance of context are required. You must determine the number of contexts to be created in the application; make sure that the context exists when the application needs it, instead of re-creating it when it is destroyed and required repeatedly.

When a context is no longer needed, it should be destroyed and released for use by other programs. Based on the scope of JS usage in the application, it can be destroyed in time after use, or it can be retained and reused until the application ends. In either case, call the js_destroycontext function when the context is no longer needed to release it. This function carries a pointer parameter pointing to the context to be released:

Js_destroycontext (CX );

If your application creates multiple runtimes, the application may need to know which runtime the context is associated. In this case, you can call the js_getruntime function and pass the context as the parameter. Js_getruntime returns a pointer pointing to the appropriate Runtime (if any ):

RT = js_getruntime (CX );

When you create a context, you need to assign stack space to it to store variables and objects. In a given context, you can also store a large amount of data. However, you must minimize the required stack space. Call the js_setcontextprivate function to create a pointer pointing to the private data required by the context. Call the js_getcontextprivate function to obtain 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 the context: first, create private data, that is, the General C language void * variable; then, call the js_setcontextprivate function, and specify the context of the created private data and the pointer to the data. For example:

Js_setcontextprivate (CX, pdata );

To obtain the Data Pointer, call js_getcontextprivate and pass the context as the parameter. This function returns a pointer to private data:

Pdata = js_getcontextprivate (CX );

<?xml encoding="US-ASCII"?><!ELEMENT order (header,item+,price)><!ELEMENT header (billing,shipping)><!ELEMENT billing (name,address,creditCard)><!ELEMENT shipping (name,address)><!ELEMENT name EMPTY>



Back to Top

Object Processing

1. Create built-in objects and global JS objects

The JavaScript engine provides several built-in objects to simplify your development tasks. For example, the built-in array object makes it easy to create and operate the array structure in the JS engine. Similarly, a date object provides a unified mechanism for operating dates. To learn about all the content supported by built-in objects, see js_initstandardclasses. The JS engine always uses functions and global objects. Generally, Global Objects stay behind the scenes and provide the default range for other JS objects and global variables created and used in the application. Before creating your own object, you must initialize the global object. Function objects allow objects to have and call constructor functions.

A Simple API call, js_initstandardclasses, initializes global and function objects and built-in engine objects to facilitate application use of them:

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

The js_initstandardclasses function returns a JS Boolean value, indicating whether the initialization is successful or not.

You can also specify another global object for the application. For example, navigator uses window as its global object. To change the global object of an application, call js_setglobalobject. For more information, see js_setglobalobject.

2. Create and initialize a custom object

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

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

  1. Write a JS script that creates an object, nature, method, and constructor, and then passes the script to the JS engine.
  2. Insert code into your application. It defines the nature and method of the object, calls the engine to initialize a new object, and then sets the nature of the object through an additional engine call. The advantage of this method is that the application can contain local methods for operating objects.

In either case, if you create an object and store it in the runtime used by other scripts, you can call js_addref and js_addnamedroot to make the object the root. Using these functions ensures that the JS engine can trace these objects and clear them when collecting fragments.

3. How to embed custom objects into Applications

It is very useful to insert a custom object into an application. For example, when the object persists, or you know that multiple scripts need to use one object. To insert a custom object to an application, follow these steps:

  • Create a jspropertyspec data type and assign the property information of the object to it, including the get and put method names of the attributes.
  • Create a jsfunctionspec data type and assign the method information used by your object to it.
  • Create the actual C functions that are executed in response to your object method call.
  • Call the js_newobject and js_constructobject functions to instantiate the object.
  • Call the js_definefunctions function to create an object.
  • Call the js_defineproperties function to create object attributes.

The code that describes continuous and custom JS objects must be placed near the beginning of program execution, before the code that is expected to have previously existed objects.

4. provide private data to objects

Like context, you can associate a large amount of data with objects instead of directly storing the data in objects. Call the js_setprivate function to create a pointer to the private data of the object. Call the js_getprivate function to obtain the pointer so that you can access the data. Your application is responsible for creating and managing the private data.

How to create a private data and associate it with an object:

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

For example:

Js_setcontextprivate (CX, OBJ, pdata );

To obtain the data, call the js_getprivate function and pass the object as a parameter. This function returns a pointer to the private data of the object:

Pdata = js_getcontextprivate (CX, OBJ );



Back to Top

Data Processing

1. Processing JS Data Types

Javascript defines its own data type. Some data types correspond directly to copies in C language. Others, such as jsobject, jsdouble, and jsstring, are unique to JavaScript.

In general, you can declare and use JS Data Types in applications just like using standard C language data types, the JS engine maintains separate stacks for 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. If not, the engine collects them and releases the storage space.

2. Process JS values

In addition to the JS data type, the JS engine also uses JS values, called jsvals. A jsval is essentially a pointer to JS data types other than integer types. For an integer, A jsval contains the value itself. In other cases, the pointer is encoded to contain additional information. Jsvals is used to improve engine efficiency and allow API functions to process a large amount of potential data types. The engine API contains a set of macros used to test a jsval JS data type. They are:

  • Jsval_is_object
  • Jsval_is_number
  • Jsval_is_int
  • Jsval_is_double
  • Jsval_is_string
  • Jsval_is_boolean

In addition to testing the potential data type of a jsval, you can also test whether 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 pointed to by jsval 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 convert jsval to its potential type using jsval_to_object, jsval_to_double, and jsval_to_string.

3. Process 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 pointing to the JS character array, that is, jschar, use a class to process unicode encoded strings. This engine also implements a set of universal Unicode string programs. Finally, the JS engine provides built-in String Support. Two or more independent strings can share one string in the memory. For jsstring strings, this engine tracks and manages string resources.

Generally, when you use the JS engine to manipulate strings, you should use the js api string processing function to create and copy strings. A string manager is used to create a string ending with null or a string of the specified length. At the same time, some programs are used to calculate the string length and compare strings.

4. Support for Unicode and interned strings

Like other API calls, the names of Unicode-enabled API string functions correspond to the names of standard engine API string functions one by one. For example, if a standard function is named js_newstringcopyn, the corresponding Unicode 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 ". When you know that the program will create a specific, text string and want to use it multiple times, use the interned string.

The engine provides several calls for the interned string:

  • Js_internstring, used to create or use a jsstring again.
  • Js_internucstring, used to create or use a unicode type jsstring again.
  • Js_internucstringn is used to create or use a fixed-length Unicode type jsstring.

5. Security Control

For javascript1.3, The JS engine adds a secure and enhanced API function for compiling and running 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 implemented by the application itself.

A common scenario in which security mechanisms are used in applications that support Javascript is to compare the authenticity of scripts or limit the interactivity of scripts. For example, you can compare the code libraries of two or more scripts in an application, and only allow scripts from the same code library to modify the script attributes of the shared code library.

To implement secure JS, follow these steps:

1) declare one or more jsprincipals structures in the program.

2) Implement functions that provide security information to arrays. These functions include: A principals array is provided for your application, and a set of rules are used to add or subtract the reference numbers of JS objects.

3) Use your security information to assign values to the jsprincipals structure. This information can include common code information.

4) Compile and execute all scripts and functions in the runtime environment. The following lists these API functions and their purposes:

  • Js_compilescriptforprincipals: compiles but does not execute a secure script.
  • Js_compileucscriptforprincipals: compiles but does not execute a script with the security capability and Unicode encoding.
  • Js_compilefunctionforprincipals: Creates a secure JS function using a text string.
  • Js_compileucfunctionforprincipals: Creates a JS function with security information using a Unicode-encoded text string.
  • Js_evaluatescriptforprincipals: Compile and execute a secure script.
  • Js_evaluateucscriptforprincipals: Compile and execute a script with the security capability and Unicode encoding.



Back to Top

Program example

The following is a simple sample program. It reads a script from the file test. JS, explains the execution, and outputs the result. The User-Defined Object "people" can be embedded in the script. The people object has attributes "name" and "Address) and method print (the name and address of the person are displayed on the screen ).

For example, the following is a simple JS script. It first outputs the name and address of the person using the print method, and then modifies the name and address to John and Beijing respectively, finally, output the name and address again to check whether 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 m_ainfo = {" 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 = trim (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 setpeopleprope Rty (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, example (JSS), 63); break ;}} return js_true ;} /* define the print method */static jsbool peopleprint (jscontext * CX, jsobject * OBJ, uintn argc, jsval * argv, jsval * rval) {fprintf (stdo Ut, "My name is % S. \ nmy ADDR is % S. \ n ", m_ainfo.name, m_ainfo.addr); 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, role, js_propertystub, js_propertystub, role }; /* define the attribute array of The People class */ST Atic jspropertyspec peopleproperties [] = {"name", my_name, jsprop_enumerate}, {"Address", my_address, jsprop_enumerate}, {0 }}; /* method array for defining the people class */static jsfunctionspec peoplemethods [] ={{ "print", peopleprint, 0 },{ 0 }}; /* define people class */static jsclass peopleclass = {"people", 0, js_propertystub, js_propertystub, getpeopleproperty, setpeopleproperty, role, js_resolvestub, js_convertstub, Js_finalizestub}; typedef struct {}/* initialize JS runtime and return the result to RT */RT = js_init (000000l); If (! RT) return;/* create a context and associate it with JS runtime */Cx = js_newcontext (RT, 5120); If (! CX) return;/* create a global object */If (! (Globalobj = js_newobject (CX, & global_class, null, null) return;/* instantiate the built-in object and Global Object */js_initstandardclasses (CX, globalobj ); /* instantiate people object */peopleobj = js_defineobject (CX, globalobj, "people", & peopleclass, 0, jsprop_enumerate);/* Create object attributes */js_defineproperties (CX, peopleobj, peopleproperties);/* method for creating an object */js_definefunctions (CX, peopleobj, peoplemethods); file * FP;/* open the file and read the script */If (! (FP = fopen ("test. JS "," R ") return; Len = fread (BUF, 1, 5120, FP); fclose (FP); If (LEN <= 0) return; /* execute a script */js_evaluatescript (CX, globalobj, Buf, Len, "", 1, & rval); JSS = js_valuetostring (CX, rval); fprintf (stdout, "The result is: % s", js_getstringbytes (JSS);/* release context */js_destroycontext (CX);/* release runtime */js_destroyruntime (RT); return ;}

Spidermonkey-DOTNET is a binding between the original JavaScript Engine spidermonkey and. NET platform. future releases will include easy to use JavaScript wrappers. net objects, and possibly the exposure of. net class library to Js.

Homepage:
Http://www.codeplex.com/developer.?view.aspx? Projectname = spidermonkeydotnet
ZIP:
Http://codeplex.com/developer.w.ectname?spidermonkeydotnet&releaseid=605
Bug tracker:
Http://www.codeplex.com/developer.w.list.aspx? Projectname = spidermonkeydotnet
Demo site:
Http://codepraxis.com

Use spidermonkey to enable C ++ applications to support the Javascript script engine
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.