In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
How to carry out JavaScript-C/C++ engine embedded development, I believe that many inexperienced people do not know what to do. Therefore, this paper summarizes the causes and solutions of the problem. Through this article, I hope you can solve this problem.
Overview of JavaScript-C/C++ engine
This document provides an overview of the C language implementation of the JavaScript (JS) engine, which shows you how to embed script engines in your applications so that they can use JS. There are two reasons to embed the JS engine in your application: use scripts to automate your application, and use JS engines and scripts to provide cross-platform functionality at any time and eliminate the platform dependence of application solutions.
Supported JavaScript version
This JS engine supports JS version 1. 0 to JS1.4. JS 1.3 and later conforms to the ECMAScript-262 specification. The JS engine parses, compiles, and executes scripts that contain JS statements and functions. This engine can handle JS data types and object memory allocations that are used to execute scripts, while it can clear-garbage collection-data types and objects that are no longer needed in memory.
How do you use this engine?
Typically, you build the JS engine as a shared resource. For example, on Windows and Windows NT, the engine is a DLL file and a shared library on Unix. Then you connect your application to it, and the embedded JS engine application programming interface (API) can be called in your application. The API of the JS engine provides the following categorized functions:
Data type operation
Run-time control
Maintenance of class and object creation
Function and script execution
string manipulation
Error handling
Safety control
Debug support
You will use some of these functional categories, such as runtime control and data type manipulation, in every application that embeds JS calls. For example, before you can call other JS functions, you must create and initialize the JS engine by calling the JS_NewRuntime function. Other functional categories, such as security controls, provide optional features that you can use in your application as needed.
What does this engine have to do with the application?
Conceptually, the JS engine is a shared resource on your system. You can pass the processed request to the JS engine by embedding the engine API command in your application. This engine, in turn, processes your request and returns the return value or status information to your application. Figure 1.1 depicts their general relationship:
Figure 1.1
For example, suppose you are using the JS engine to enable your application to run automatically through JS scripts, and suppose your application runs a script to authenticate a user and set a user's access to the application. First, your application may create a custom JS object that represents the user, including the user's name, ID, access rights, and a list of functions that the user may have permissions to use in the application.
In this case, the first request your application sends to the JS engine may be a call to JS_NewObject to create a new custom object. When the JS engine creates this object, it returns a pointer to your application. Your application can call the JS engine again to execute a script that uses this object. For example, after creating a user object, your application will immediately pass a script to JS_EvaluateScript to compile and execute immediately. That script can obtain and validate user information and then establish user access to other application features.
In fact, the relationship between your application and the JS engine is much more complex than that shown in figure 1.1. For example, it assumes that you have built a JS engine for your platform. It also assumes that your application contains jsapi.h and that the first call to the engine by the application has initialized the JS runtime.
When the JS engine receives an initialization request, it allocates memory for the JS runtime. Figure 1.2 depicts this process:
Figure 1.2
This runtime is a memory space in which you can maintain the variables, objects, and contexts used by your application. One context is the script execution state for the threads used by the JS engine. Each simultaneous script or thread must have its own context. A single JS runtime can contain many contexts, objects, and variables.
Almost all JS engine calls require a context parameter, so the first thing your application needs to do after creating the runtime is to call JS_NewContext to create at least one context. The actual number of contexts you need is determined by the number of scripts expected to run at the same time in your application. On the other hand, if only one script is compiled and executed at a time, you know that you need to establish a separate context, and you can reuse it for each script.
After you create a new context, you will usually want to initialize the JS object built into the engine, which can be done by calling JS_InitStandardClasses. The built-in objects are Array,Boolean,Date,Math,Number, and String string objects, which are used by most scripts.
Most applications also use custom JS objects. These objects are specific to your application. They usually represent data structures and the methods used by scripts in the application. To create a new custom object, you assemble a JS class to generate the object, call JS_InitClass to set up the class at run time, and then call JS_NewObject to create a new instance of your custom object in the engine. Finally, if your object has some properties, you may want to set their default values by calling JS_SetProperty.
Even if you pass a specific context to the JS engine when you create an object, in the end the object exists independent of that context. Any script can be associated with any context to access any object. Figure 1.3 depicts the relationship between scripts and runtime, context, and objects.
Figure 1.3
As shown in figure 1.3, the script and context are completely independent of each other even if they can access the same object. In a given runtime, an application can access any object in any unassigned context. There may also be times when you want to make sure that certain contexts and objects are reserved for exclusive use. In these cases, create a new separate runtime for your application: one for shared context and objects, and the other (or more, depending on your application's needs) for private runtimes and objects.
Note: only one thread can be authorized to access a specific context at a time.
Build engine
Before you can use JS in your application, you must build the JS engine into a shareable library. In most cases, the engine code already includes Make files to build automatically.
For example, under Unix, the js source code directory includes a basic Gnu Make file-- Makefile.ref-- and a config directory. The config directory includes platform-specific .mk files to work with Makefile.ref to build your environment. In Windows
Under NT, the NMake file is js.mak.
Please read any readme file in the source code directory, which may include and update compilation instructions or other information.
What are the necessary conditions for embedding engines?
If you want your application to execute JS, you need to embed the appropriate engine in your application code. There are generally five steps to embedding:
Add # include jsapi.h to your C module to make sure the compiler knows which engines' API can be called. Very few special JS engines require you to include additional header files when they work. For example, to call the JS debugger in your application, you need to include jsdbgapi.h in the appropriate module.
Other header files that are mostly in the JS source code should not be referenced. Doing so may make your program dependent on the interfaces within the engine, which may change with the release.
Provide supporting structures and variable declarations in your application. For example, if you plan to pass a script to the JS engine, provide a string variable that holds the text message about the version of your application's script. Declare structures and variables using the JS data type defined in jsapi.h.
Use JavaScript to write application-specific objects. These objects often communicate with structures and methods that operate on the structure in your C program, especially if you are using the JS engine to automate your application.
Embed appropriate JS engine API calls and variable references in the program code, including initializing built-in JS objects and creating custom objects that make up any application.
Most JS engine calls return a value. If this value is zero or empty, it usually indicates that an error has occurred. If the value is non-zero, it usually indicates success; in these cases, the returned value will often be the pointer your program needs to use, or save it for later reference. It is important that your program at least check the value returned by the JS call every time.
The following code snippet describes most of the process used for embedding, which is beyond the scope of this article except for the creation of JS scripts. For information about creating scripts-- the JavaScript language-- see the client-side JavaScript instructions, and for more information on writing server-side objects, see server-side JavaScript instructions.
.
.
.
# include
# include
# include
/ * include JS engine API header file * /
# include "jsapi.h"
.
.
.
/ * the main program establishes global JS variables, including runtime
* A context, and a global object, and then initialize the JS runtime
* and create a context. , /
Int main (int argc, char * * argv)
{
Int c, i
/ * create global JS variables, including global and custom objects * /
JSVersion version
JSRuntime * rt
JSContext * cx
JSObject * glob, * it
JSBool builtins
/ * initialize the JS runtime and return the result to rt * /
Rt = JS_NewRuntime (8L * 1024L * 1024L)
/ * if rt has no value, end the program * /
If (! rt)
Return 1
/ * create a new context and associate it with the JS runtime * /
Cx = JS_NewContext (rt, 8192)
/ * if cx has no value, end the program here * /
If (cx = = NULL)
Return 1
/ * create a new global object * /
Glob = JS_NewObject (cx, clasp, NULL, NULL)
/ * initialize built-in JS objects and global objects * /
Builtins = JS_InitStandardClasses (cx, glob)
.
.
.
Return 0
}
This sample code is simple enough to describe the key elements necessary to embed JS engine calls. For a more complete example-- that's where the above snippet comes from-- see js.c, where the source code for the sample application is included in the source code of the JS engine.
Understand key embedded development concepts
Most of the JavaScript applications you want to create, you will want to follow some authoritative JS API embedding practices. The following sections describe the API calls that are used in any program.
In many cases, the order in which certain API calls are embedded determines the success of the program. For example, you must initialize a JS runtime before calling other JS engine functions. Accordingly, you need to release the JS runtime before closing the program. Therefore, the main function of a typical program is like a sandwich, initializing and then releasing the JS runtime before and after any functionality you provide:
Int main (int argc, char * * argv)
{
Int c, i
/ * create global JS variables, including global objects global and custom objects * /
JSVersion version
JSRuntime * rt
JSContext * cx
JSObject * glob, * it
.
.
.
/ * initialize the JS runtime and put the returned results in rt * /
Rt = JS_NewRuntime (8L * 1024L * 1024L)
/ * if rt has no value, the program ends. , /
If (! rt)
Return 1
.
.
.
/ * create a context * /
Cx = JS_NewContext (rt, 8192)
/ * if the cx value is empty, end the program * /
If (cx = = NULL)
Return 1
/ * initialize built-in JS objects and global objects * /
Builtins = JS_InitStandardClasses (cx, glob)
.
.
.
/ * throw your code here, including the JS API function calls you want to use to create custom JS objects.
* the JS object model starts here. , /
.
.
.
/ * release the JS runtime before exiting the application * /
JS_DestroyRuntime (rt)
As described in this example, the application that embeds the functions of the JS engine is responsible for building the JS runtime, which is one of its first actions, and it is also responsible for releasing the runtime before exiting. In general, the best place to ensure that the runtime is initialized and released is to embed the necessary calls in the module of the central JS scheduler, no matter which module you will use as the central scheduling module in the application.
After you initialize the runtime, you can build the JS object model of the application. This object model determines how your JS objects relate to each other. JS objects are hierarchical in nature. All JS objects are associated with global (global) objects by default, 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)
Global objects establish some basic properties and methods, which are inherited by other objects. When you create your own objects, they can automatically use these properties and methods that have been defined on the global object. You can override these default properties and methods by redefining them on custom objects, otherwise you can directly accept the default assignments.
You can also create new custom objects based on other built-in JS objects, or create new objects based on other custom objects. In either case, the object you create will inherit all the properties and methods of its ancestors in the inheritance chain, all the way back to the global object. To learn more about global and custom objects, see initializing built-in and global JS objects and creating and initializing custom objects.
Manage a runtime
The JS runtime is a piece of memory space in which the JS engine can manage the context, objects, and variables associated with JS functions and scripts. You must initialize a runtime before executing any JS function or script. The API call to initialize the runtime is JS_NewRuntime. JS_NewRuntime has one parameter, which is an unsigned integer that indicates the maximum memory allocated to the runtime before garbage collection occurs, in bytes. For example:
Rt = JS_NewRuntime (8L * 1024L * 1024L)
As listed above, JS_NewRuntime also returns a value, which is a pointer to the newly created runtime. A non-empty return value indicates that the runtime was created successfully.
In general, an application needs only one runtime. However, you can still create multiple runtimes, and we can call JS_NewRuntime if necessary and store the return values in different pointers.
When the JS runtime is no longer needed, it should be destroyed to free up memory resources for other applications to use. Depending on the scope of use of JS in your application, you can choose to destroy the runtime immediately after JS use, or you can choose to keep the runtime until your application is coming to an end. In either case, you must use JS_DestroyRuntime to release the runtime when the runtime is no longer needed:
JS_DestroyRuntime (rt)
If you use multiple runtimes, make sure that each is released correctly before ending the application.
Administrative context
Almost all JS API calls require you to pass a context as an argument. In the JavaScript engine, a context uniquely corresponds to a script. The engine sends context information to the thread running the script. Each synchronized script must be assigned a unique context. When a script is executed, its context is no longer used, and the context can be assigned to a new script again, or it can be released.
To create a new context for a script, you can use the JS_NewContext function. This function takes two parameters: a pointer to the runtime that the context needs to combine, and the size of the stack space allocated for the context, in bytes. If successful, the function returns a pointer to the newly created context. For example:
JSContext * cx
.
.
.
Cx = JS_NewContext (rt, 8192)
The runtime must already exist. The stack you specify for the context should be large enough to accommodate any variables and objects created by scripts that use that context. Note that there is a specific amount related to the context of allocation and maintenance, because you may want to:
Only create as many contexts as you need in your application at the same time.
Keep the context as long as it is possible for the application to use it, rather than destroy it every time you create a new one when you don't need it.
When a context is no longer needed, it should be destroyed to free up its memory resources for other applications. Depending on the scope of JS use in your application, you can choose to destroy the context immediately after using it, or, more often, you can consider reusing it for later use to preserve the context until the end of the application. In either case, JS_DestroyContext can be used to release the context when he no longer needs it. This function takes an argument, that is, a pointer to the context to destroy:
JS_DestroyContext (cx)
If your application creates multiple runtimes, the application needs to know which runtime is associated with the context. In this case, you can call JS_GetRuntime and pass the context to him as an argument. JS_GetRuntime returns a pointer to an appropriate runtime, if it exists:
Rt = JS_GetRuntime (cx)
When you create a context, you assign it stack space that will be used by variables and objects created by scripts that use that context. You can also use a given context only to store a large amount of data, as long as the minimum stack space required is allocated. Call the JS_SetContextPrivate function to establish a pointer to the private data used by the context, and call the JS_GetContextPrivate function to get the pointer so that the data can be accessed. Your application is responsible for creating and managing this optional private data.
To create private data and associate it with a context:
To create private data as needed, you can use a normal C void pointer variable.
Call JS_SetContextPrivate and indicate the context in which the private data is created, and give a pointer to the data.
For example:
JS_SetContextPrivate (cx, pdata)
If you want to get the data later, call the JS_GetContextPrivate function and pass him the context as an argument. This function returns a pointer to private data:
Pdata = JS_GetContextPrivate (cx); initializes built-in and global JS objects
The JavaScript engine provides some built-in objects that will simplify some of your development tasks. For example, the built-in Array object makes it easier for you to create and process array structures in the JS engine. Similarly, the Date object provides a unified mechanism for dealing with date data. For a complete list of built-in objects supported by the engine, see JS_InitStandardClasses.
The JS engine always uses functions and global objects. In general, global objects exist behind the scene of a JS script, providing a default space scope for all other JS objects and storing global variables that you create and use in the program. Before you can create your own object, you need to initialize the global object. The function object enables object support and constructor calls.
JS_InitStandardClasses, this API call will initialize global and function objects as well as objects built into the engine so that your application can use them:
JSBool builtins;...builtins = JS_InitStandardClasses (cx, glob)
JS_InitStandardClasses returns a JS boolean value to indicate whether the initialization was successful.
You can specify a different global object for your application. For example, Netscape Navigator uses his own global object, window. To change the global object for your application, call the JS_SetGlobalObject function. Please refer to the reference entry for JS_SetGlobalObject for more information.
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 important if you use JS engine processing scripts to automate your application. Custom JS objects can provide the most direct program services, and they can also be used as an interface to your program services. For example, a custom JS object provides some kind of direct service, such as handling all the network access of the application and acting as the middle layer of the data service. It can also be mapped to future data and functions in the application using a JS object, which provides an object-oriented interface for C code. Such a custom object acts as an interface to the application itself-passing values from the application to the user, accepting and processing the user's input, and then returning it to the application. Such objects can also be used to control access to functions within the application.
There are two ways to create custom objects:
Write a JS script to create an object, along with its properties, methods, and constructors, and then pass the script to the JS engine at run time.
Embed the code that defines the properties and methods of the object in your program, call the engine to initialize the new object, and then set the properties of the object through other engine calls. One advantage of this approach is that your program can include local methods that directly deal with embedded objects.
In either case, if you create an object and want to persist it at run time so that it can be called by other objects at run time, you must determine the "root" of the object through JS_AddRoot or JS_AddNamedRoot calls. Using these two functions ensures that the JS engine keeps track of these objects and cleans them up during garbage collection when appropriate.
Create an object from a script
One reason to create a custom JS object from a script is that only one object exists while the script is running. To create such an object that persists during a script call, you can also embed the object's code directly in your application without using a script.
Note: you can also use scripts to create persistent objects.
To create a custom object using a script:
Define and describe objects. What is his purpose? What are his data members (attributes)? What methods (functions) does he have? Does he need a runtime constructor?
Write JS scripts that define and create objects. For example:
Function myfun () {
Var x = newObject ()
.
.
.
}
Note: objects written in JavaScript are not in the code that the application embeds into the JS engine. For more information about object writing, see the client-side JavaScript Guide and the Server-side JavaScript Guide.
Embed the appropriate JS engine call in the application to compile and execute the script. You have two choices: 1.) Use only one function call to compile and execute the script: JS_EvaluateScript,JS_EvaluateUCScript or 2.)
Use JS_CompileScript or JS_CompileUCScript to compile the script at once, and then you can call JS_ExecuteScript. Exe with a separate function.
To repeat the compiled code. The "UC" version of these calls provides support for Unicode scripts.
An object you create using a script can only be enabled during the life cycle of the script, or it can be persisted after the end of the script. Generally speaking, once the script is finished, all his objects will be destroyed. In most cases, this behavior is exactly what your application needs. In other cases, however, you may want an object to stay between scripts, or for the entire life cycle of your application. In this case, you need to embed object creation code directly in your application, or you must connect the object directly to the global object so that it will last as long as the global object itself exists.
Embed a custom object in the application
Embedding a custom JS object is useful in an application when object persistence is necessary, or when you think you need an object that is available to several scripts. For example, a custom object that represents the user's ID and access rights may be used throughout the lifetime of the application. He creates and assembles objects at once in advance, saving a lot of time without having to use scripts to create objects over and over again every time you have to verify a user's ID or permissions.
One way to embed custom objects in an application is:
Create a JSPropertySpec data type and assemble it and the property's information into the object's properties, including the name of the parameter get and set method.
Create a JSFunctionSpec data type and assemble the information about it and the method into the methods used by the object.
Create an actual C function to handle the object's method calls.
Call JS_NewObject or JS_ConstructObject to instantiate the object.
Call JS_DefineFunctions to create the method of this object.
Call JS_DefineProperties to create the properties of this object.
The code that describes the persistent custom JS object must be placed near the beginning of the application execution, before any code that depends on the object. Embedded engine calls to instantiate and assemble custom objects should also appear before any code that depends on this object.
Note: in most cases, a more convenient way to create a custom object in program code is to call JS_DefineObject to create the object, and then repeatedly call JS_SetProperty to set the object's properties. For more information about defining an object, see JS_DefineObject. For more information about setting object properties, see JS_SetProperty.
Provide private data for objects
Like context, you can associate a large amount of data with an object without having to store the data in that object. Call JS_SetPrivate to set up a pointer to private data, and call JS_GetPrivate to get the pointer so that the data can be accessed. Your application is responsible for the creation and management of these optional private data.
To create private data and associate it with an object:
To create private data as needed, you can use a normal C void pointer variable.
Call JS_SetPrivate, specify that you want to create private data for that object, and give a pointer to the data.
For example:
JS_SetPrivate (cx, obj, pdata)
If you want to get the data later, call JS_GetPrivate and pass the object as a parameter. This function returns a pointer to the object's private data:
Pdata = JS_GetPrivate (cx, obj); handle Unicode (Unicode)
The JS engine now provides Unicode-enabled versions of many API functions. These functions allow you to pass Unicode-encoded scripts directly to the engine to compile and run. The following table lists the standard engine functions and their corresponding Unicode versions:
Standard function
Unicode support 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
The unified code function works in the same way as the original function of the same name, except that the original function uses the parameter char *, while the unified code version uses the parameter jschar
*.
Manipulate JS data types
JavaScript defines his own data type. Some of them directly correspond to the copies in C. Others, such as JSObject,jsdouble
And JSString, yes.
JavaScript has a special meaning.
In general, you declare and use JS data types in your application the same way you use standard C data types. However, the JS engine treats the JS data type, that is, the variable JSObject,jsdouble that requires more than one word space
Has a different tracking than JSString. The engine periodically checks these variables to see if they are still in use. If you no longer use them, collect them and free up storage space for reuse.
Garbage collection can effectively reuse heap resources, but excessive garbage collection can also have an impact on performance. You can control the frequency of garbage collection according to the JS runtime, according to the relationship between the size of the JS runtime you assign to the program and the number of JS variables and objects used by your application. If your program creates and uses many JS objects and variables, you may have to allocate a large enough runtime to reduce the possible frequency of garbage collection.
Note that your application should call JS_GC or JS_MaybeGC at any time to enforce garbage collection. JS_GC will enforce garbage collection. JS_MaybeGC performs garbage collection on a conditional basis, if a specific proportion of the space allocated at initialization is already used when you call this function.
Manipulate JS value
In addition to the JS data type, the JS engine also uses JS values, called jsval. A jsval is essentially a pointer to any JS data type (except integers). For integers, jsval directly contains its own integer values. In other cases, the pointer is encoded to add additional information about the type of data it refers to. Use can improve the efficiency of the engine, but also allow many API functions to deal with different types of data.
The engine API contains a set of macros to test the JS data type in the JS value. There are:
JSVAL_IS_OBJECT
JSVAL_IS_NUMBER
JSVAL_IS_INT
JSVAL_IS_DOUBLE
JSVAL_IS_STRING
JSVAL_IS_BOOLEAN
Besides testing ajsval, you can also check whether it belongs to a basic JS data type (JSVAL_IS_PRIMITIVE). Basic types include undefined (undefined), empty (null),
Boolean (boolean), numeric (numeric), and string (string) types.
You can test whether the value referred to by jsval is NULL (JSVAL_IS_NULL)
Or void (JSVAL_IS_VOID).
If jsval points to an JS data type that is JSObject,jsdouble
Or jsstr, you can convert jsval to its internal type, as long as you use JSVAL_TO_OBJECT,JSVAL_TO_DOUBLE and JSVAL_TO_STRING accordingly. In some cases, your application or JS engine calls require the use of a variable or parameter of a specific data type rather than a jsval. Similarly, you can use OBJECT_TO_JSVAL,DOUBLE_TO_JSVAL
And STRING_TO_JSVAL, put JSObject,jsdouble
And jsstr are converted to jsval accordingly.
Manipulate JS strings
A lot of your work in JavaScript involves strings. The JS engine implements a JS string type, JSString, a pointer to the JS character-jschar- array, which is used to process strings that support Unicode. The engine also implements a series of rich general-purpose and Unicode string managers. Finally, the JS engine provides support for qualified strings, which allow two or more identical strings to be created to share a separate instance in memory. For strings of type JSString, the engine tracks and manages string resources.
In general, when you are dealing with strings used by the JS engine, you should use the string handler in JS API to create and copy strings. There are also routines for creating strings of a specific length that end with a null character, as well as getting the string length and comparing strings.
Unicode string support
The name of the API string function using Unicode (Unicode) corresponds to the number of standard engine API string lines one by one. The rule is as follows: if the standard function name is JS_NewStringCopyN, the corresponding Unicode version is JS_NewUCStringCopyN. There are also API string functions that support Unicode for qualified strings.
Qualified string support
To save storage space, the JS engine provides support for sharing a separate instance of strings that belong to independent, immutable text. Such shared strings are called "qualified strings" (interned string). When you think that a particular text will be created and used repeatedly in the program, you can use a qualified string.
The engine's API provides several function calls that work on qualified strings:
JS_InternString
Used to create or reuse a JSString.
JS_InternUCString
Used to create or reuse a Unicode JSString.
JS_InternUCStringN
Used to create or reuse a fixed-length Unicode JSString.
Manage security
Now using the JavaScript 1.3 JS engine, security-enhanced API functions have been added to compile and execute scripts and functions passed to the engine. The JS security model is based on Java's basic security model. The model provides a public security interface, but the actual security control is up to you.
A common way to use security management in applications that use JavaScript is to compare the sources of scripts and restrict their interaction. For example, you might compare the code sources of two or more scripts and only allow scripts from the same code source to modify the properties of scripts that share the code source.
To implement secure JS, follow these steps:
Declare a struct of one or more JSPrincipals types in your code.
Add a list of functions that implement security information to the array. These include functions that provide an array of principles for the program, and a mechanism for increasing or decreasing the reference count of JS objects that use a given principle.
Assemble the JSPrincipals structure with your security information. This information can include general code source information.
At run time, specific JS API calls are used to compile and execute all scripts and functions that apply security, and they will require that a JSPrincipals structure be passed. The following table lists these API functions and their functions:
Function
Purpose
JS_CompileScriptForPrincipals
Compile (but not execute) a script that enables security control.
JS_CompileUCScriptForPrincipals
Compile (but not execute) a Unicode-encoded script that enables security control.
JS_CompileFunctionForPrincipals
Create a JS function that enables security control from a text string.
JS_CompileUCFunctionForPrincipals
Create a JS function with security information from a Unicode-encoded string.
JS_EvaluateScriptForPrincipals
Compile and execute a script that enables security control.
JS_EvaluateUCScriptForPrincipals
Compile and execute a script that enables security control and is encoded in Unicode.
Article source: url https://developer.mozilla.org/en-US/docs/SpiderMonkey/JSAPI_User_Guide
Implementation tutorial:
SpiderMonkey
SpiderMonkey is part of the Mozilla project, a JavaScript scripting engine implemented in C, and a Java version called Rhino.
First you need to download the latest version of SpiderMonkey. The download package is distributed in source code. This requires you to compile your own script engine. For Visual C++ users, the project files can be found in the src- directory. The compilation result is a dynamic library called "js32.dll". SpiderMonkey can also be applied to
Based on Macintosh and Unix platform. To learn how to compile SpiderMonkey on other platforms, see ReadMe.html.
The World of SpiderMonkey
In order to run JavaScript code in SpiderMonkey, the application must have three elements: JSRuntime,JSContext and global objects.
Runtime environment
JSRuntime, which allocates space for JavaScript variables, objects, scripts, and contexts used in applications. Every JSContext and every object in the script lives in a JSRuntime. They cannot be transferred to or shared with other runtimes. Generally speaking, most applications only need a runtime environment.
Context
JSContext, like a small machine, involves a lot of things about JavaScript code and objects. It can compile and execute scripts, get and set object properties, call JavaScript functions, convert one type to another JavaScript data, create objects, and so on. Almost all JSAPI functions take a JSContext* as their first argument, just as most functions need FILE*.
Global object
The global object contains all the classes, functions, and variables that can be used in JavaScript code.
When the JavaScript code is about to do something, such as window.open ("http://www.mozilla.org/"), which is actually accessing a global property (the property of the global object), in this case window.
The global properties that can be seen by the script are completely controlled by the application. The application first creates an object and adds standard JavaScript classes such as Array and Object. Then add any custom classes, functions, and variables that the program wants to add (like window here). Each time the application runs a js script (for example, using JS_EvaluateScript), it provides the global object that the script uses. As for the script, it can also create its own global functions and variables. All of these functions, classes, and variables are stored as properties in the global object.
Execute the JavaScript script in C++ step 1-create a JavaScript runtime environment (runtime)
The JavaScript runtime environment is initialized by calling JS_NewRuntime. It is responsible for allocating the memory resources required by the runtime environment. You need to specify the number of bytes allocated, beyond which the fragment collector will execute.
JSRuntime * rt = JS_NewRuntime (1000000L); if (rt = = NULL) {/ / Do some error reporting} step 2-create a context (context)
The context specifies the size of the stack in the script and allocates the specified size of memory as the execution stack of the script. Each script is associated with its own context. When the context is used by one script or thread, other scripts or threads cannot use it. When the script or thread ends, this context can be reused to the next script or thread.
Create a new context with the JS_NewContext method. A context is associated with a runtime environment, and you must specify the size of the stack.
JSContext * cx = JS_NewContext (m_rt, 8192); if (cx = = NULL) {/ / Do some error reporting} step 3-initialize the global object (global object)
Before the script can be executed, you must initialize the JavaScript normal function and create a large number of objects in the script.
Global object (global object) is described by JSClass structure. Initialize this structure as follows:
JSClass globalClass = {"Global", 0, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub}
Now you can create the global object and initialize it:
JSObject * globalObj = JS_NewObject (cx, & globalClass, 0,0); JS_InitStandardClasses (cx, globalObj); step 4-execute script
One way to execute a script is to use the JS_EvaluateScript method.
Std::string script = "var today = Date (); today.toString (); jsval rval;uintN lineno = 0; JS_EvaluateScript (cx, globalObj, script.c_str (), script.length ()," script ", lineno, & rval)
When the script runs without errors, today's date is saved in rval. Rval saves the final execution result of the function. The return value of JS_EvaluateScript: JS_TRUE for success and JS_FALSE for error.
The value to retrieve the string from rval is as follows. Every detail will not be demonstrated here. Check information about API when you need it.
JSString * str = JS_ValueToString (cx, rval); std::cout setCustomer (new Customer ()); if (! JS_SetPrivate (cx, obj, p) return JS_FALSE; * rval = OBJECT_TO_JSVAL (obj); return JS_TRUE;}
This constructor method can have multiple parameters and can be used to initialize your class. Now that you have created a pointer on the heap, you need a way to destroy it. This can be done through the static method JS_Destructor.
Void JSCustomer::JSDestructor (JSContext * cx, JSObject * obj) {JSCustomer * p = JS_GetPrivate (cx, obj); delete p; p = NULL;} step 3-add attributes
Add a static array member of type JSPropertySpec. This array will contain attribute information. Then create an enumeration of the attribute ID number (enum).
Static JSPropertySpec customer_properties []; enum {name_prop,age_prop}
Initialize the array in the implementation file as follows
JSPropertySpec JSCustomer::customer_properties [] = {{name ", name_prop, JSPROP_ENUMERATE}, {" age ", age_prop, JSPROP_ENUMERATE}, {0}}
The last element of the array must be empty (NULL). Each element contains another array of three elements. The first element is the name, which will be used in the JavaScript script. The second element is the unique ID number of the attribute and will be passed to the callback function. The third element is a flag. JSPROP_ENUMERATE means that it is visible in the script when enumerating this property of the Customer object, that is, it can be used in for or in statements in the script. You can specify the JSPROP_READONLY property to indicate that this property cannot be modified.
Now it's time to implement the callback functions for getting (getting) and setting (setting) properties:
JSBool JSCustomer::JSGetProperty (JSContext * cx, JSObject * obj, jsval id, jsval * vp) {if (JSVAL_IS_INT (id)) {Customer * priv = (Customer *) JS_GetPrivate (cx, obj); switch (JSVAL_TO_INT (id)) {case name_prop: break Case age_prop: * vp = INT_TO_JSVAL (priv- > getCustomer ()-> GetAge ()); break;}} return JS_TRUE } JSBool JSCustomer::JSSetProperty (JSContext * cx, JSObject * obj, jsval id, jsval * vp) {if (JSVAL_IS_INT (id)) {Customer * priv = (Customer *) JS_GetPrivate (cx, obj); switch (JSVAL_TO_INT (id)) {case name_prop: break Case age_prop: priv- > getCustomer ()-> SetAge (JSVAL_TO_INT (* vp)); break;}} return JS_TRUE;}
Remember to return JS_TRUE in the property callback. When you return JS_FALSE, it will indicate that this property is not found in your object.
Step 4-add method
Create an array of static members of type JSFunctionSpec.
Static JSFunctionSpec customer_methods []
Initialize the array in the implementation file as follows
JSFunctionSpec wxJSFrame::wxFrame_methods [] = {{"computeReduction", computeReduction, 1,0,0}, {0}}
The last element of the array must be empty (NULL). Each element contains another array of five elements. The first element is the name of the function used in the script. The second element is the global or static member function name. The third element is the number of arguments to this function. The last two elements are ignored.
Create a static method in the class
Static JSBool computeReduction (JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
Returns JS_TRUE when the function succeeds, JS_FALSE otherwise. The actual return value of your JavaScript method is put in the rval parameter.
An example of implementing this method
JSBool JSCustomer::computeReduction (JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval) {JSCustomer * p = JS_GetPrivate (cx, obj); if (p-> getCustomer ()-> GetAge () < 25) * rval = INT_TO_JSVAL (10); else * rval = INT_TO_JSVAL (5); return JS_TRUE;} an example
The following script uses the object created above
Var c = new Customer (); c.name = "Franky"; c.age = 32 world var reduction = c.computeReduction ()
Don't forget to initialize the JavaScript object when the context is created:
JSObject * obj = JSCustomer::JSInit (cx, global)
Code / / main.cpp demonstrates how to execute javascript # define XP_PC#include # include "JSCustomer.h" JSClass globalClass = {"Global", 0, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub}; void main (int argc, char * argv []) {if (argc < 2) {std::cout
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.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.