首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

功能强大的JavaScript引擎--SpiderMonkey简介2

功能强大的JavaScript引擎--SpiderMonkey简介2

管理RunTimeJSRunTime是内存空间,JS引擎利用它来管理上下文、对象和与JS函数及脚本相关的变量。在执行JS函数或脚本之前,首先要调用JS_NewRunTime来初始化一个RunTime。JS_NewRunTime函数携带一个unsigned整型参数,这个参数指定了在碎片收集之前分配给RunTime内存的最大字节数。例如:
rt = JS_NewRuntime(8L * 1024L * 1024L);
如上所示,JS_NewRuntime返回一个指向RunTime的指针。非NULL表示创建成功。
正常情况下,一个程序只需一个RunTime。当然,根据需要创建多个RunTime并将它们保存在不同指针上也是可以的。
JS_DestroyRuntime(rt);
如果你创建了多个RunTime,务必在应用程序终止前将每个都销毁。
管理上下文(Contexts)几乎所有的JSAPI调用都要求你传递一个上下文参数。在JavaScript引擎中一个上下文代表一个脚本,引擎传递上下文信息给运行脚本的线程。每个同时运行的脚本必须指派一个唯一的上下文。当一个脚本运行完后,它的上下文也不再有用,因此这个上下文可以重新指派给一个新的脚本,或将其释放。
调用函数JS_NewContext为某个脚本创建一个新的上下文。这个函数需要两个参数:一个与该上下文相关的RunTime指针,分配给该上下文的栈空间字节数。如果调用成功,函数返回一个指针,它指向这个新建立的上下文。例如:
1
2
3
4
5
JSContext *cx;
      .
      .
      .
cx = JS_NewContext(rt, 8192);




这个RunTime必须已经存在。你指派给上下文的栈空间必须足够大以便提供给使用该上下文的脚本所创建的变量和对象。注意,因为需要一些与分配和维护上下文相关的overhead,你必须做到:在应用程序中必须根据需要来确定创建上下文的数量;要确保上下文在被应用程序所需要时存在,而不是反复销毁和需要时重新创建。
当某个上下文不再需要时,它应被销毁、释放内存资源给其它程序使用。根据应用程序中JS使用的范围,可以在使用完后及时销毁,或将其保留并反复利用直到应用程序终止。无论哪种情况,当上下文不再需要时都要调用函数JS_DestroyContext来释放它,这个函数携带一个指针参数,它指向要被释放的上下文:
JS_DestroyContext(cx);
如果你的应用程序创建了多个RunTime,那么,应用程序可能需要知道某个上下文是与哪个RunTime相关联的。这种情况下,可以调用函数JS_GetRuntime,同时传递该上下文作为参数。JS_GetRuntime返回一个指针,它指向合适的RunTime(如果存在的话):
rt=JS_GetRuntime(cx);
当你创建一个上下文,你要给它指派栈空间用于存放变量和对象。在一个给定的上下文中,你也能够存放大量的数据。但是,你必须将所需的栈空间尽可能地降到最小。调用JS_SetContextPrivate函数创建一个指针,它指向该上下文所需的私有数据,调用JS_GetContextPrivate函数得到这个指针以便你能存取这数据。你的应用程序负责创建和管理私有数据。
要创建私有数据并将其与上下文相关联:首先,创建私有数据,即常规的C语言void* 变量;然后,调用JS_SetContextPrivate函数,并指定创建私有数据的上下文和指向该数据的指针。例如:
JS_SetContextPrivate(cx,pdata);
随后要获取这个数据指针,请调用JS_GetContextPrivate,并传递这个上下文作为参数。这个函数返回指向私有数据的指针:
pdata=JS_GetContextPrivate(cx);
1
2
3
4
5
6
<?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>




对象的处理1.创建内置对象和全局JS对象
JavaScript引擎提供若干个内置对象,使得你的开发任务得以简化。例如,内置数组(Array)对象使得在JS引擎中创建和操作数组结构很容易。类似地,日期(Date)对象提供了一个操作日期的统一机制。要了解内置对象支持的全部内容,请参阅JS_InitStandardClasses。JS引擎一直使用函数和全局对象。通常,全局对象居留在幕后,为应用程序中创建和使用的其它JS对象及全局变量提供缺省范围。在创建自己的对象前,你必须初始化全局对象。函数对象使得对象具有和调用构造函数的功能。
一个简单的API调用,JS_InitStandardClasses,初始化全局和函数对象、内置引擎对象,方便应用程序使用它们:
1
2
3
4
5
JSBool builtins;
      .
      .
      .
builtins = JS_InitStandardClasses(cx, glob);




JS_InitStandardClasses函数返回一个JS布尔值,表示初始化成功与否。
你也可以为应用程序指定另外一个不同的全局对象。例如,Navigator使用window作为其全局对象。要改变应用程序的全局对象,请调用JS_SetGlobalObject。要了解更多信息,请参阅JS_SetGlobalObject。
2.创建并初始化自定义对象
除了使用引擎内置对象外,你还可以创建、初始化并使用自己的JS对象。特别是你在使用JS引擎用脚本来自动化应用程序时更是如此。自定义的JS对象能提供直接的程序服务,或者作为你的程序服务的接口。
有两种方法来创建JS引擎能使用的自定义对象:
  • 写一个JS脚本,它创建一个对象、性质、方法、构造函数,然后将这个脚本传递给JS引擎。
  • 将代码插入到你的应用程序中,它定义了对象的性质和方法,调用引擎来初始化一个新对象,然后通过额外的引擎调用设置对象的性质。这种方法的好处是,应用程序能包含操作对象的本地方法。
无论哪种情况,如果你创建一个对象,然后让其存在于被其它脚本使用的RunTime中,你可以调用JS_AddRef和JS_AddNamedRoot使该对象为根。使用这些函数,确保JS引擎能跟踪这些对象并在碎片收集时清除它们。
3.如何将自定义对象嵌入到应用程序中
将自定义对象插入到应用程序中是很有用的,比如,当对象持续需要时,或者你知道有多个脚本需要使用一个对象。将自定义对象插入到应用程序中的步骤是:
  • 创建一个JSPropertySpec数据类型,将对象的属性信息指派给它,包括属性的GET和PUT方法名字。
  • 创建一个JSFunctionSpec数据类型,将被你的对象所使用的方法信息指派给它。
  • 创建实际的C函数,它们在响应你的对象方法调用时被执行。
  • 调用JS_NewObject和JS_ConstructObject函数,以便实例化该对象。
  • 调用JS_DefineFunctions函数来创建对象的方法。
  • 调用JS_DefineProperties函数来创建对象的属性。
描述持续的、自定义的JS对象的代码必须放在靠近程序执行的开始部分,在那些依耐于先前已存在对象的代码之前。
4.给对象提供私有数据
象上下文一样,你可以将大量的数据与对象进行关联,而不是将这些数据直接存放在对象里。调用JS_SetPrivate函数来创建指向对象私有数据的指针,调用JS_GetPrivate函数来获取这个指针以便你能存取这些数据。你的应用程序负责创建和管理这些私有数据。
创建私有数据并将其与对象关联的方法:
1)创建私有数据,作为C语言的void*变量。 2)调用JS_SetPrivate函数,指定对象和私有数据指针。
例如:
JS_SetContextPrivate(cx,obj,pdata);
随后,要获取这些数据,请调用JS_GetPrivate函数,将对象作为参数进行传递。这个函数返回指向对象私有数据的指针:
pdata=JS_GetContextPrivate(cx,obj);
数据处理1.处理JS数据类型
JavaScript定义了自己的数据类型。有些数据类型直接对应于C语言中的副本。其它的,如JSObject、jsdouble和JSString,都是JavaScript独有的。
通常,你可以在应用程序中像使用标准的C语言数据类型一样声明、使用JS数据类型,JS引擎对那些需要多于一个字存储空间的JS数据类型的变量保持单独的栈,例如:JSObject、jsdouble和JSString。引擎会周期性地检查这些变量,看看它们是否仍在使用,如果没有,引擎就碎片收集它们,释放存储空间。
2.处理JS值
除了JS数据类型以外,JS引擎也使用JS值,称其为jsvals。一个jsval本质上是一个指针,指向除了整型以外的JS数据类型。对于整型,一个jsval包含这个值自身。其它情况,指针被编码成包含额外信息。利用jsvals提高引擎的效率,允许API函数处理大量的潜在数据类型。引擎API包含一组宏,用于测试一个jsval的JS数据类型。他们是:
  • JSVAL_IS_OBJECT
  • JSVAL_IS_NUMBER
  • JSVAL_IS_INT
  • JSVAL_IS_DOUBLE
  • JSVAL_IS_STRING
  • JSVAL_IS_BOOLEAN
除了测试一个jsval的潜在数据类型外,也能测试它看是否是原始JS数据类型(JSVAL_IS_PRIMITIVE)。原始数据类型是undefined、null、boolean、numeric和string类型。
你也可测试jsval指向的值是否为NULL(JSVAL_IS_NULL)或void(JSVAL_IS_VOID)。
如果一个jsval指向一个JSObject、 jsdouble或jsstr等JS数据类型,你可利用JSVAL_TO_OBJECT、 JSVAL_TO_DOUBLE、JSVAL_TO_STRING将jsval转为它的潜在类型。
3.处理JS字符串
你在JavaScript中做的许多事情都会涉及到字符串,JS引擎实现了一个称为JSString的字符串数据类型和一个指向JS字符数组的指针类型即jschar,用类处理Unicode编码的字符串。这个引擎也实现了一组通用的Unicode字符串程序。最后,JS引擎也提供内置串的支持,两个或多个独立的字符串在内存中能共享一个串。对于JSString类型的字符串,这个引擎跟踪并管理串资源。
一般说来,当你用JS引擎操纵字符串时,你应该用JSAPI串处理函数来创建和复制字符串。有字符串管理程序用于创建NULL结尾的字符串或者指定长度的字符串。同时,也有程序用于计算字符串长度、比较字符串。
4.对Unicode和Interned字符串的支持
像其他API调用一样,具有Unicode能力的API字符串函数的名字与标准的引擎API字符串函数的名字是一一对应的。例如,如果一个标准函数名为JS_NewStringCopyN,对应的Unicode版函数就是JS_NewUCStringCopN。具有Unicode处理能力的API字符串函数对于interned字符串也是可行的。
为了节约空间,JS引擎为共享单个字符串实例提供支持。这种共享的字符串称为"internedstrings"。当你事先知道程序中会创建一个特定的、文本字符串并且要多次使用它时,请利用interned字符串。
引擎为interned字符串提供了若干个调用:
  • JS_InternString,用于创建或再次使用一个JSString。
  • JS_InternUCString,用于创建或再次使用一个Unicode类型的JSString。
  • JS_InternUCStringN,用于创建或再次使用固定长度的Unicode型JSString。
5.安全控制
对于JavaScript1.3,JS引擎增加了安全增强型API函数,用于编译和运行传递给引擎的脚本或函数。JS安全模型是基于Java安全模型的。这个模型提供了一个通用的安全接口,但是,具体的安全实现是由应用程序自己来完成的。
安全机制用在能够支持JavaScript的应用程序中的一种通用情形是比较脚本的真实性或者限制脚本的交互性。例如,你可以比较一个应用程序中两个或多个脚本的代码库,只允许来自同一个代码库的脚本能够修改共享代码库的脚本属性。
如果要实现安全JS,请按以下步骤:
1)在程序中声明一个或者多个JSPrincipals类型的结构。
2)实现将给数组提供安全信息的函数。这些函数包括:给你的应用程序提供一个principals数组,用一套给定的规则对JS对象的引用数进行加减操作的机制。
3)用你的安全信息给JSPrincipals结构赋值,这个信息可以包括通用代码信息。
4)在运行时间环境中,编译与执行全部脚本和函数。下面列出了这些API函数和它们的目的:
  • JS_CompileScriptForPrincipals:编译但不执行一段具有安全能力的脚本。
  • JS_CompileUCScriptForPrincipals:编译但不执行一段具有安全能力、Unicode编码的脚本。
  • JS_CompileFunctionForPrincipals:利用一个文本字符串创建一个具有安全能力的JS函数。
  • JS_CompileUCFunctionForPrincipals:利用一个Unicode编码的文本字符串创建一个具有安全信息的JS函数。
  • JS_EvaluateScriptForPrincipals:编译并执行一段具有安全能力的脚本。
  • JS_EvaluateUCScriptForPrincipals:编译并执行一段具有安全能力、用Unicode编码的脚本。
返回列表