青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

牽著老婆滿街逛

嚴(yán)以律己,寬以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

功能強(qiáng)大的JavaScript引擎--SpiderMonkey

轉(zhuǎn)載自:http://www.ibm.com/developerworks/cn/linux/shell/js/js_engine/index.html

JavaScript是由Netscape開發(fā)的對(duì)象腳本語(yǔ)言,其特點(diǎn)是開發(fā)簡(jiǎn)單、功能靈活,目前已廣泛應(yīng)用于WEB頁(yè)面及服務(wù)器應(yīng)用程序中。HTML本身是靜態(tài)的、不允許用戶干預(yù),但用JavaScript編寫的腳本程序就可以在用戶的瀏覽器端運(yùn)行,可以同用戶進(jìn)行交互,從而實(shí)現(xiàn)動(dòng)態(tài)頁(yè)面??梢詫avaScript與嵌入WEB的大多數(shù)對(duì)象的事件(如鼠標(biāo)點(diǎn)擊、移動(dòng)等)相關(guān)聯(lián),然后用自己的方式處理這些事件。JavaScript提供了豐富的內(nèi)置函數(shù)及命令,能在瀏覽器中顯示HTML、數(shù)值計(jì)算、多媒體播放、超級(jí)鏈接以及簡(jiǎn)單的交互窗口等,還可以使在瀏覽器中運(yùn)行的小Java應(yīng)用程序的性質(zhì)改變從而很容易地改變控件或其它對(duì)象的行為而不必深入研究其本身的結(jié)構(gòu)。

JavaScript雖然是為Internet而開發(fā)的,但它的應(yīng)用卻不僅僅局限于Internet,事實(shí)上由于其面向?qū)ο蟮奶匦允沟闷溥m用范圍非常廣泛,只要我們的應(yīng)用程序具有良好的對(duì)象機(jī)制,我們就可以借用JavaScript,從而實(shí)現(xiàn)很好的交互功能。

SpiderMonkey是由C語(yǔ)言操作的JavaScript引擎,它支持JS1.4和ECMAScript-262規(guī)范。該引擎分析、編譯和執(zhí)行腳本,根據(jù)JS數(shù)據(jù)類型和對(duì)象的需要進(jìn)行內(nèi)存分配及釋放操作。利用該引擎可以讓你的應(yīng)用程序具有解釋JavaScript腳本的能力,目前已有若干個(gè)項(xiàng)目都采用了SpiderMonkey引擎,像K-3D、WebCrossing、WebMerger等。K-3D是用C++實(shí)現(xiàn)的3D建模與仿真系統(tǒng),該系統(tǒng)內(nèi)嵌SpiderMonkey引擎來(lái)提供自定義腳本(用戶創(chuàng)建腳本生成像齒輪一樣具有重復(fù)特性的復(fù)雜形體),也可用來(lái)驅(qū)動(dòng)交互式的教學(xué)系統(tǒng)(用戶可以使用一段JS腳本程序記錄其交互過程,如移動(dòng)鼠標(biāo)、選擇菜單、點(diǎn)擊鼠標(biāo)等)。WebCrossing利用SpiderMonkey實(shí)現(xiàn)了服務(wù)器端的腳本環(huán)境,提供了完全的Web-server腳本環(huán)境,服務(wù)器端的實(shí)現(xiàn)允許你在內(nèi)置的、面向?qū)ο蟮臄?shù)據(jù)庫(kù)中創(chuàng)建永久對(duì)象,這樣即可根據(jù)自己的需要擴(kuò)展服務(wù)器環(huán)境。

下面簡(jiǎn)要介紹在自己的應(yīng)用程序中如何使用SpiderMonkey,最后給出一個(gè)簡(jiǎn)單的例子程序。

如何使用引擎

JS引擎一般作為共享庫(kù)使用,應(yīng)用程序調(diào)用引擎提供的API函數(shù)。引擎API函數(shù)大致分為以下幾種:數(shù)據(jù)類型操作、RunTime控制、類與對(duì)象的創(chuàng)建和維護(hù)、函數(shù)與腳本執(zhí)行、字符串操作、錯(cuò)誤處理、安全控制、Debug支持。 一般情況下,在你的應(yīng)用程序中只需使用某幾類函數(shù)。例如,在進(jìn)行JS調(diào)用之前你必須調(diào)用JS_NewRuntime函數(shù)來(lái)創(chuàng)建并初始化JS引擎。有些類型的函數(shù),象安全控制類,提供可選擇的特征。

從概念上講,JS引擎是你系統(tǒng)上的一個(gè)共享資源。通過將引擎API調(diào)用嵌入到應(yīng)用程序中(包含jsapi.h文件),你可以請(qǐng)求JS引擎進(jìn)行操作。接下來(lái),引擎處理你的請(qǐng)求,并將結(jié)果或狀態(tài)信息返回給你的應(yīng)用程序。

例如,假定你在使用JS引擎自動(dòng)化應(yīng)用程序,腳本應(yīng)用程序鑒別用戶并設(shè)置權(quán)限。首先,應(yīng)用程序創(chuàng)建JS對(duì)象,該對(duì)象描述用戶信息,包括姓名、ID、權(quán)限和可用的函數(shù)列表。在這種情況下,應(yīng)用程序首先調(diào)用JS_NewObject創(chuàng)建對(duì)象。當(dāng)JS引擎創(chuàng)建對(duì)象后,返回一個(gè)指針給應(yīng)用程序。應(yīng)用程序再調(diào)用JS引擎執(zhí)行腳本。在創(chuàng)建用戶對(duì)象后,應(yīng)用程序即刻傳遞腳本給JS_EvaluateScript以便編譯和運(yùn)行。腳本或許取得并效驗(yàn)用戶信息,然后建立用戶存取的權(quán)利。

JS引擎收到初始化請(qǐng)求后,給JS RunTime分配內(nèi)存,應(yīng)用程序使用的變量、對(duì)象和上下文(上下文)都保存在RunTime中。一個(gè)上下文是腳本的執(zhí)行狀態(tài)(JS引擎使用的)。每個(gè)同時(shí)存在的腳本或線程都必須有自己的上下文。單個(gè)的JS RunTime可以包含多個(gè)上下文、對(duì)象和變量。 幾乎所有的JS引擎調(diào)用都需要一個(gè)上下文變量,應(yīng)用程序在創(chuàng)建RunTime后,首先應(yīng)調(diào)用至少一次JS_NewContext來(lái)創(chuàng)建一個(gè)上下文。上下文的實(shí)際數(shù)量依賴于程序中同時(shí)使用的腳本數(shù)。程序中每個(gè)同時(shí)存在的腳本都需要一個(gè)上下文。另一方面,如果某個(gè)時(shí)刻只有一個(gè)腳本編譯和運(yùn)行,那么你只需一個(gè)上下文給每個(gè)腳本重復(fù)使用即可。

在創(chuàng)建上下文后,要調(diào)用JS_InitStandardClasses初始化引擎中的內(nèi)置JS對(duì)象,包括Array、Boolean、Date、Math、Number和String。 即使在創(chuàng)建對(duì)象時(shí)傳遞一個(gè)特定的上下文給JS引擎,這個(gè)對(duì)象在RunTime中也是獨(dú)立于上下文。任意腳本能與任意上下文建立聯(lián)系以便存取任意對(duì)象。腳本、上下文相互之間完全獨(dú)立,即使它們存取同樣的對(duì)象。在給定的RunTime中,應(yīng)用程序能用未指定的上下文存取任意對(duì)象。你可以創(chuàng)建獨(dú)立的RunTime,一個(gè)用于共享上下文和對(duì)象,其余的用于私有上下文和對(duì)象。但注意,某個(gè)時(shí)刻只有一個(gè)線程能存取特定的上下文。 要讓應(yīng)用程序能識(shí)別JS,嵌入適當(dāng)?shù)囊嬲{(diào)用到你的程序中。大致有以下幾個(gè)方面:

  1. 程序中包含jsapi.h。
  2. 程序中提供結(jié)構(gòu)和變量聲明。例如,如果你計(jì)劃傳遞一個(gè)腳本給JS引擎,提供一個(gè)腳本字符串變量。用jsapi.h中定義的JS數(shù)據(jù)類型來(lái)聲明變量。
  3. 使用JavaScript的腳本應(yīng)用對(duì)象。通常這些對(duì)象與C程序中的結(jié)構(gòu)和方法相對(duì)應(yīng)。
  4. 將JS引擎API函數(shù)調(diào)用和變量引用插入到程序中,包括初始化內(nèi)置JS對(duì)象、創(chuàng)建并配置用戶自定義對(duì)象。
  5. 大多數(shù)JS引擎調(diào)用返回一個(gè)值。如果該值是NULL,一般表示錯(cuò)誤發(fā)生。如果非NULL,表示成功,返回值一般是指針,程序需要使用或留到將來(lái)使用。應(yīng)用程序應(yīng)檢查JS引擎調(diào)用的返回值。

要讓應(yīng)用程序能解釋JavaScript,你必須遵循某些JS API嵌入習(xí)慣。下面的例子簡(jiǎn)要說(shuō)明需要嵌入到你的應(yīng)用程序中去的一些API調(diào)用函數(shù)。大部分情況下,這些函數(shù)的插入順序是很重要的。例如,在調(diào)用其他JS API之前必須初始化JS RunTime,同樣在終止程序之前必須釋放JS RunTime。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 包含JS引擎的API頭文件 */
#include "jsapi.h"
.
.
.
//主程序聲明全局JS變量,包括RunTime、一個(gè)Context和一個(gè)全局對(duì)象,然后初始化JS RunTime、創(chuàng)建一個(gè)Context。
int main(int argc, char **argv)
{
  int c, i;
  /*聲明全局JS變量,包括全局和自定義對(duì)象*/
  JSVersion version;
  JSRuntime *rt;
  JSContext *cx;
  JSObject  *glob, *it;
  JSBool builtins;
  /* 初始化JS RunTime,返回結(jié)果給rt */
  rt = JS_NewRuntime(8L * 1024L * 1024L);
  /* 如果rt為空,程序終止 */
  if (!rt)
    return 1;
  /* 創(chuàng)建一個(gè)Context,并將其與JS RunTime關(guān)聯(lián)起來(lái) */
  cx = JS_NewContext(rt, 8192);
  /* 如果cx為空,程序終止 */
  if (cx == NULL)
    return 1;
  /* 創(chuàng)建全局對(duì)象 */
  glob = JS_NewObject(cx, clasp, NULL, NULL);
  /* 實(shí)例化內(nèi)置對(duì)象和全局對(duì)象*/
  builtins = JS_InitStandardClasses(cx, glob);
  .
  .
  .
  return 0;
}

如上面這個(gè)例子所示,調(diào)用JS引擎的應(yīng)用程序必須首先創(chuàng)建JS RunTime,而且在終止程序之前要釋放這個(gè)RunTime。在實(shí)例化RunTime后,即可創(chuàng)建自己的JS對(duì)象模型。對(duì)象模型決定了JS對(duì)象之間的關(guān)系,JS對(duì)象本質(zhì)上是一種層次結(jié)構(gòu)。缺省情況下,所有的JS對(duì)象都與全局對(duì)象相關(guān)聯(lián),它們都是全局對(duì)象的后代。當(dāng)初始化標(biāo)準(zhǔn)的JS類時(shí),你自動(dòng)地得到一個(gè)全局對(duì)象:

builtins = JS_InitStandardClasses(cx, glob);

這個(gè)全局對(duì)象創(chuàng)建了一些基本的、被其它對(duì)象所繼承的性質(zhì)和方法。當(dāng)你創(chuàng)建自定義對(duì)象時(shí),它們自動(dòng)使用全局對(duì)象所定義的性質(zhì)和方法。你可以在自定義對(duì)象上重新定義這些性質(zhì)和方法,從而重載這些缺省的性質(zhì)和方法。當(dāng)然,你也可以接受這些缺省的分配。 你可以在內(nèi)置JS對(duì)象或其它自定義對(duì)象的基礎(chǔ)上創(chuàng)建自己的對(duì)象。無(wú)論哪種情況,你所創(chuàng)建的對(duì)象都繼承了層次鏈中父對(duì)象、一直上溯到全局對(duì)象的全部性質(zhì)和方法。

管理RunTime

JS RunTime是內(nèi)存空間,JS引擎利用它來(lái)管理上下文、對(duì)象和與JS函數(shù)及腳本相關(guān)的變量。在執(zhí)行JS函數(shù)或腳本之前,首先要調(diào)用JS_NewRunTime來(lái)初始化一個(gè)RunTime。JS_NewRunTime函數(shù)攜帶一個(gè)unsigned整型參數(shù),這個(gè)參數(shù)指定了在碎片收集之前分配給RunTime內(nèi)存的最大字節(jié)數(shù)。例如:

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

如上所示,JS_NewRuntime返回一個(gè)指向RunTime的指針。非NULL表示創(chuàng)建成功。

正常情況下,一個(gè)程序只需一個(gè)RunTime。當(dāng)然,根據(jù)需要?jiǎng)?chuàng)建多個(gè)RunTime并將它們保存在不同指針上也是可以的。

JS_DestroyRuntime(rt);

如果你創(chuàng)建了多個(gè)RunTime,務(wù)必在應(yīng)用程序終止前將每個(gè)都銷毀。

管理上下文(Contexts)

幾乎所有的JS API調(diào)用都要求你傳遞一個(gè)上下文參數(shù)。在JavaScript引擎中一個(gè)上下文代表一個(gè)腳本,引擎?zhèn)鬟f上下文信息給運(yùn)行腳本的線程。每個(gè)同時(shí)運(yùn)行的腳本必須指派一個(gè)唯一的上下文。當(dāng)一個(gè)腳本運(yùn)行完后,它的上下文也不再有用,因此這個(gè)上下文可以重新指派給一個(gè)新的腳本,或?qū)⑵溽尫拧?/p>

調(diào)用函數(shù)JS_NewContext為某個(gè)腳本創(chuàng)建一個(gè)新的上下文。這個(gè)函數(shù)需要兩個(gè)參數(shù):一個(gè)與該上下文相關(guān)的RunTime指針,分配給該上下文的??臻g字節(jié)數(shù)。如果調(diào)用成功,函數(shù)返回一個(gè)指針,它指向這個(gè)新建立的上下文。例如:

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

這個(gè)RunTime必須已經(jīng)存在。你指派給上下文的棧空間必須足夠大以便提供給使用該上下文的腳本所創(chuàng)建的變量和對(duì)象。注意,因?yàn)樾枰恍┡c分配和維護(hù)上下文相關(guān)的overhead,你必須做到:在應(yīng)用程序中必須根據(jù)需要來(lái)確定創(chuàng)建上下文的數(shù)量;要確保上下文在被應(yīng)用程序所需要時(shí)存在,而不是反復(fù)銷毀和需要時(shí)重新創(chuàng)建。

當(dāng)某個(gè)上下文不再需要時(shí),它應(yīng)被銷毀、釋放內(nèi)存資源給其它程序使用。根據(jù)應(yīng)用程序中JS使用的范圍,可以在使用完后及時(shí)銷毀,或?qū)⑵浔A舨⒎磸?fù)利用直到應(yīng)用程序終止。無(wú)論哪種情況,當(dāng)上下文不再需要時(shí)都要調(diào)用函數(shù)JS_DestroyContext來(lái)釋放它,這個(gè)函數(shù)攜帶一個(gè)指針參數(shù),它指向要被釋放的上下文:

JS_DestroyContext(cx);

如果你的應(yīng)用程序創(chuàng)建了多個(gè)RunTime,那么,應(yīng)用程序可能需要知道某個(gè)上下文是與哪個(gè)RunTime相關(guān)聯(lián)的。這種情況下,可以調(diào)用函數(shù)JS_GetRuntime,同時(shí)傳遞該上下文作為參數(shù)。JS_GetRuntime返回一個(gè)指針,它指向合適的RunTime(如果存在的話):

rt=JS_GetRuntime(cx);

當(dāng)你創(chuàng)建一個(gè)上下文,你要給它指派棧空間用于存放變量和對(duì)象。在一個(gè)給定的上下文中,你也能夠存放大量的數(shù)據(jù)。但是,你必須將所需的??臻g盡可能地降到最小。調(diào)用JS_SetContextPrivate函數(shù)創(chuàng)建一個(gè)指針,它指向該上下文所需的私有數(shù)據(jù),調(diào)用JS_GetContextPrivate函數(shù)得到這個(gè)指針以便你能存取這數(shù)據(jù)。你的應(yīng)用程序負(fù)責(zé)創(chuàng)建和管理私有數(shù)據(jù)。

要?jiǎng)?chuàng)建私有數(shù)據(jù)并將其與上下文相關(guān)聯(lián):首先,創(chuàng)建私有數(shù)據(jù),即常規(guī)的C語(yǔ)言void* 變量;然后,調(diào)用JS_SetContextPrivate函數(shù),并指定創(chuàng)建私有數(shù)據(jù)的上下文和指向該數(shù)據(jù)的指針。例如:

JS_SetContextPrivate(cx,pdata);

隨后要獲取這個(gè)數(shù)據(jù)指針,請(qǐng)調(diào)用JS_GetContextPrivate,并傳遞這個(gè)上下文作為參數(shù)。這個(gè)函數(shù)返回指向私有數(shù)據(jù)的指針:

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>

對(duì)象的處理

1.創(chuàng)建內(nèi)置對(duì)象和全局JS對(duì)象

JavaScript引擎提供若干個(gè)內(nèi)置對(duì)象,使得你的開發(fā)任務(wù)得以簡(jiǎn)化。例如,內(nèi)置數(shù)組(Array)對(duì)象使得在JS引擎中創(chuàng)建和操作數(shù)組結(jié)構(gòu)很容易。類似地,日期(Date)對(duì)象提供了一個(gè)操作日期的統(tǒng)一機(jī)制。要了解內(nèi)置對(duì)象支持的全部?jī)?nèi)容,請(qǐng)參閱JS_InitStandardClasses。 JS引擎一直使用函數(shù)和全局對(duì)象。通常,全局對(duì)象居留在幕后,為應(yīng)用程序中創(chuàng)建和使用的其它JS對(duì)象及全局變量提供缺省范圍。在創(chuàng)建自己的對(duì)象前,你必須初始化全局對(duì)象。函數(shù)對(duì)象使得對(duì)象具有和調(diào)用構(gòu)造函數(shù)的功能。

一個(gè)簡(jiǎn)單的API調(diào)用,JS_InitStandardClasses,初始化全局和函數(shù)對(duì)象、內(nèi)置引擎對(duì)象,方便應(yīng)用程序使用它們:

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

JS_InitStandardClasses函數(shù)返回一個(gè)JS布爾值,表示初始化成功與否。

你也可以為應(yīng)用程序指定另外一個(gè)不同的全局對(duì)象。例如,Navigator使用window作為其全局對(duì)象。要改變應(yīng)用程序的全局對(duì)象,請(qǐng)調(diào)用JS_SetGlobalObject。要了解更多信息,請(qǐng)參閱JS_SetGlobalObject。

2.創(chuàng)建并初始化自定義對(duì)象

除了使用引擎內(nèi)置對(duì)象外,你還可以創(chuàng)建、初始化并使用自己的JS對(duì)象。特別是你在使用JS引擎用腳本來(lái)自動(dòng)化應(yīng)用程序時(shí)更是如此。自定義的JS對(duì)象能提供直接的程序服務(wù),或者作為你的程序服務(wù)的接口。

有兩種方法來(lái)創(chuàng)建JS引擎能使用的自定義對(duì)象:

  1. 寫一個(gè)JS腳本,它創(chuàng)建一個(gè)對(duì)象、性質(zhì)、方法、構(gòu)造函數(shù),然后將這個(gè)腳本傳遞給JS引擎。
  2. 將代碼插入到你的應(yīng)用程序中,它定義了對(duì)象的性質(zhì)和方法,調(diào)用引擎來(lái)初始化一個(gè)新對(duì)象,然后通過額外的引擎調(diào)用設(shè)置對(duì)象的性質(zhì)。這種方法的好處是,應(yīng)用程序能包含操作對(duì)象的本地方法。

無(wú)論哪種情況,如果你創(chuàng)建一個(gè)對(duì)象,然后讓其存在于被其它腳本使用的RunTime中,你可以調(diào)用JS_AddRef和JS_AddNamedRoot使該對(duì)象為根。使用這些函數(shù),確保JS引擎能跟蹤這些對(duì)象并在碎片收集時(shí)清除它們。

3.如何將自定義對(duì)象嵌入到應(yīng)用程序中

將自定義對(duì)象插入到應(yīng)用程序中是很有用的,比如,當(dāng)對(duì)象持續(xù)需要時(shí),或者你知道有多個(gè)腳本需要使用一個(gè)對(duì)象。將自定義對(duì)象插入到應(yīng)用程序中的步驟是:

  • 創(chuàng)建一個(gè)JSPropertySpec數(shù)據(jù)類型,將對(duì)象的屬性信息指派給它,包括屬性的GET和PUT方法名字。
  • 創(chuàng)建一個(gè)JSFunctionSpec數(shù)據(jù)類型,將被你的對(duì)象所使用的方法信息指派給它。
  • 創(chuàng)建實(shí)際的C函數(shù),它們?cè)陧憫?yīng)你的對(duì)象方法調(diào)用時(shí)被執(zhí)行。
  • 調(diào)用JS_NewObject和JS_ConstructObject函數(shù),以便實(shí)例化該對(duì)象。
  • 調(diào)用JS_DefineFunctions函數(shù)來(lái)創(chuàng)建對(duì)象的方法。
  • 調(diào)用JS_DefineProperties函數(shù)來(lái)創(chuàng)建對(duì)象的屬性。

描述持續(xù)的、自定義的JS對(duì)象的代碼必須放在靠近程序執(zhí)行的開始部分,在那些依耐于先前已存在對(duì)象的代碼之前。

4.給對(duì)象提供私有數(shù)據(jù)

象上下文一樣,你可以將大量的數(shù)據(jù)與對(duì)象進(jìn)行關(guān)聯(lián),而不是將這些數(shù)據(jù)直接存放在對(duì)象里。調(diào)用JS_SetPrivate函數(shù)來(lái)創(chuàng)建指向?qū)ο笏接袛?shù)據(jù)的指針,調(diào)用JS_GetPrivate函數(shù)來(lái)獲取這個(gè)指針以便你能存取這些數(shù)據(jù)。你的應(yīng)用程序負(fù)責(zé)創(chuàng)建和管理這些私有數(shù)據(jù)。

創(chuàng)建私有數(shù)據(jù)并將其與對(duì)象關(guān)聯(lián)的方法:

1)創(chuàng)建私有數(shù)據(jù),作為C語(yǔ)言的void*變量。 2)調(diào)用JS_SetPrivate函數(shù),指定對(duì)象和私有數(shù)據(jù)指針。

例如:

JS_SetContextPrivate(cx,obj,pdata);

隨后,要獲取這些數(shù)據(jù),請(qǐng)調(diào)用JS_GetPrivate函數(shù),將對(duì)象作為參數(shù)進(jìn)行傳遞。這個(gè)函數(shù)返回指向?qū)ο笏接袛?shù)據(jù)的指針:

pdata=JS_GetContextPrivate(cx,obj);

數(shù)據(jù)處理

1.處理JS數(shù)據(jù)類型

JavaScript定義了自己的數(shù)據(jù)類型。有些數(shù)據(jù)類型直接對(duì)應(yīng)于C語(yǔ)言中的副本。其它的,如JSObject、jsdouble和JSString,都是JavaScript獨(dú)有的。

通常,你可以在應(yīng)用程序中像使用標(biāo)準(zhǔn)的C語(yǔ)言數(shù)據(jù)類型一樣聲明、使用JS數(shù)據(jù)類型,JS引擎對(duì)那些需要多于一個(gè)字存儲(chǔ)空間的JS數(shù)據(jù)類型的變量保持單獨(dú)的棧,例如:JSObject、jsdouble和JSString。引擎會(huì)周期性地檢查這些變量,看看它們是否仍在使用,如果沒有,引擎就碎片收集它們,釋放存儲(chǔ)空間。

2.處理JS值

除了JS數(shù)據(jù)類型以外,JS引擎也使用JS值,稱其為jsvals。一個(gè)jsval本質(zhì)上是一個(gè)指針,指向除了整型以外的JS數(shù)據(jù)類型。對(duì)于整型,一個(gè)jsval包含這個(gè)值自身。其它情況,指針被編碼成包含額外信息。利用jsvals提高引擎的效率,允許API函數(shù)處理大量的潛在數(shù)據(jù)類型。 引擎API包含一組宏,用于測(cè)試一個(gè)jsval的JS數(shù)據(jù)類型。他們是:

  • JSVAL_IS_OBJECT
  • JSVAL_IS_NUMBER
  • JSVAL_IS_INT
  • JSVAL_IS_DOUBLE
  • JSVAL_IS_STRING
  • JSVAL_IS_BOOLEAN

除了測(cè)試一個(gè)jsval的潛在數(shù)據(jù)類型外,也能測(cè)試它看是否是原始JS數(shù)據(jù)類型(JSVAL_IS_PRIMITIVE)。原始數(shù)據(jù)類型是undefined、null、boolean、numeric和string類型。

你也可測(cè)試jsval指向的值是否為NULL(JSVAL_IS_NULL)或void(JSVAL_IS_VOID)。

如果一個(gè)jsval指向一個(gè)JSObject、 jsdouble或 jsstr等JS數(shù)據(jù)類型,你可利用JSVAL_TO_OBJECT、 JSVAL_TO_DOUBLE、 JSVAL_TO_STRING將jsval轉(zhuǎn)為它的潛在類型。

3.處理JS字符串

你在JavaScript中做的許多事情都會(huì)涉及到字符串,JS引擎實(shí)現(xiàn)了一個(gè)稱為JSString的字符串?dāng)?shù)據(jù)類型和一個(gè)指向JS字符數(shù)組的指針類型即jschar,用類處理Unicode編碼的字符串。這個(gè)引擎也實(shí)現(xiàn)了一組通用的Unicode字符串程序。最后,JS引擎也提供內(nèi)置串的支持,兩個(gè)或多個(gè)獨(dú)立的字符串在內(nèi)存中能共享一個(gè)串。對(duì)于JSString類型的字符串,這個(gè)引擎跟蹤并管理串資源。

一般說(shuō)來(lái),當(dāng)你用JS引擎操縱字符串時(shí),你應(yīng)該用JS API串處理函數(shù)來(lái)創(chuàng)建和復(fù)制字符串。有字符串管理程序用于創(chuàng)建NULL結(jié)尾的字符串或者指定長(zhǎng)度的字符串。同時(shí),也有程序用于計(jì)算字符串長(zhǎng)度、比較字符串。

4.對(duì)Unicode和Interned字符串的支持

像其他API調(diào)用一樣,具有Unicode能力的API字符串函數(shù)的名字與標(biāo)準(zhǔn)的引擎API字符串函數(shù)的名字是一一對(duì)應(yīng)的。例如,如果一個(gè)標(biāo)準(zhǔn)函數(shù)名為JS_NewStringCopyN,對(duì)應(yīng)的Unicode版函數(shù)就是JS_NewUCStringCopN。具有Unicode處理能力的API字符串函數(shù)對(duì)于interned字符串也是可行的。

為了節(jié)約空間,JS引擎為共享單個(gè)字符串實(shí)例提供支持。這種共享的字符串稱為"interned strings"。當(dāng)你事先知道程序中會(huì)創(chuàng)建一個(gè)特定的、文本字符串并且要多次使用它時(shí),請(qǐng)利用interned字符串。

引擎為interned字符串提供了若干個(gè)調(diào)用:

  • JS_InternString,用于創(chuàng)建或再次使用一個(gè)JSString。
  • JS_InternUCString,用于創(chuàng)建或再次使用一個(gè)Unicode類型的JSString。
  • JS_InternUCStringN,用于創(chuàng)建或再次使用固定長(zhǎng)度的Unicode型JSString。

5.安全控制

對(duì)于JavaScript1.3,JS引擎增加了安全增強(qiáng)型API函數(shù),用于編譯和運(yùn)行傳遞給引擎的腳本或函數(shù)。JS安全模型是基于Java安全模型的。這個(gè)模型提供了一個(gè)通用的安全接口,但是,具體的安全實(shí)現(xiàn)是由應(yīng)用程序自己來(lái)完成的。

安全機(jī)制用在能夠支持JavaScript的應(yīng)用程序中的一種通用情形是比較腳本的真實(shí)性或者限制腳本的交互性。例如,你可以比較一個(gè)應(yīng)用程序中兩個(gè)或多個(gè)腳本的代碼庫(kù),只允許來(lái)自同一個(gè)代碼庫(kù)的腳本能夠修改共享代碼庫(kù)的腳本屬性。

如果要實(shí)現(xiàn)安全JS,請(qǐng)按以下步驟:

1)在程序中聲明一個(gè)或者多個(gè)JSPrincipals類型的結(jié)構(gòu)。

2)實(shí)現(xiàn)將給數(shù)組提供安全信息的函數(shù)。這些函數(shù)包括:給你的應(yīng)用程序提供一個(gè)principals數(shù)組,用一套給定的規(guī)則對(duì)JS對(duì)象的引用數(shù)進(jìn)行加減操作的機(jī)制。

3)用你的安全信息給JSPrincipals結(jié)構(gòu)賦值,這個(gè)信息可以包括通用代碼信息。

4)在運(yùn)行時(shí)間環(huán)境中,編譯與執(zhí)行全部腳本和函數(shù)。下面列出了這些API函數(shù)和它們的目的:

  • JS_CompileScriptForPrincipals:編譯但不執(zhí)行一段具有安全能力的腳本。
  • JS_CompileUCScriptForPrincipals:編譯但不執(zhí)行一段具有安全能力、Unicode編碼的腳本。
  • JS_CompileFunctionForPrincipals:利用一個(gè)文本字符串創(chuàng)建一個(gè)具有安全能力的JS函數(shù)。
  • JS_CompileUCFunctionForPrincipals:利用一個(gè)Unicode編碼的文本字符串創(chuàng)建一個(gè)具有安全信息的JS函數(shù)。
  • JS_EvaluateScriptForPrincipals :編譯并執(zhí)行一段具有安全能力的腳本。
  • JS_EvaluateUCScriptForPrincipals:編譯并執(zhí)行一段具有安全能力、用Unicode編碼的腳本。

程序樣例

以下是一個(gè)簡(jiǎn)單的樣例程序,它從文件test.js中讀入一段腳本,然后解釋執(zhí)行并輸出結(jié)果。腳本中可嵌入自定義對(duì)象People,People對(duì)象具有屬性name(表示該人的姓名)、address(表示該人的地址)及方法print(在屏幕上顯示該人的姓名、地址信息)。

例如:下面是一段簡(jiǎn)單的js腳本,它首先利用print方法輸出該人的姓名和地址,然后將姓名和地址分別修改為John和Beijing,最后再次輸出其姓名和地址,看是否修改正確。

people.print();

people.name="John";

people.address="Beijing";

people.print();

下面是C源程序代碼。

#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=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;
}
/*定義print方法*/
static JSBool PeoplePrint(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, 
   jsval *rval)
{
    fprintf(stdout,"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, JS_PropertyStub,JS_PropertyStub, JS_PropertyStub,
            JS_EnumerateStub, JS_ResolveStub,JS_ConvertStub, JS_FinalizeStub };
/*定義People類的屬性數(shù)組*/
static JSPropertySpec PeopleProperties[] =
  {
    {"name", MY_NAME,    JSPROP_ENUMERATE },
    {"address",  MY_ADDRESS,     JSPROP_ENUMERATE },
    {0}
  } ;
/*定義People類的方法數(shù)組*/
static JSFunctionSpec PeopleMethods[] =
{
    {"print",          PeoplePrint,     0},
             {0}
        };
/*定義People類*/
static JSClass PeopleClass = {
        "people",0,
  JS_PropertyStub,JS_PropertyStub, GetPeopleProperty, SetPeopleProperty,
  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
};
    typedef struct{}
      /* 初始化JS RunTime,返回結(jié)果給rt */
rt = JS_Init(1000000L);
    if (!rt)return;
  /* 創(chuàng)建一個(gè)上下文,并將其與JS RunTime關(guān)聯(lián)起來(lái) */
    cx = JS_NewContext(rt, 5120);
    if (!cx)return;
  /* 創(chuàng)建全局對(duì)象 */
    if (!(globalObj = JS_NewObject (cx, &global_class, NULL, NULL)))return;
      /* 實(shí)例化內(nèi)置對(duì)象和全局對(duì)象*/
JS_InitStandardClasses (cx, globalObj);
/*實(shí)例化People對(duì)象*/
PeopleObj = JS_DefineObject (cx, globalObj, "People", &PeopleClass, 0,JSPROP_ENUMERATE);
/*創(chuàng)建對(duì)象的屬性*/
JS_DefineProperties (cx,PeopleObj, PeopleProperties);
/*創(chuàng)建對(duì)象的方法*/
JS_DefineFunctions (cx,PeopleObj, PeopleMethods);
FILE* fp;
/*打開文件,讀入腳本*/
    if (!(fp = fopen ("test.js", "r")))return;
    len = fread (buf, 1, 5120, fp);
    fclose (fp);
    if (len <= 0)return;
/*執(zhí)行一段腳本*/
    JS_EvaluateScript (cx, globalObj, buf, len, "", 1, &rval);
    jss = JS_ValueToString (cx, rval);
    fprintf(stdout,"The result is: %s",JS_GetStringBytes (jss));
/*釋放上下文*/
JS_DestroyContext(cx);
/*釋放RunTime*/
JS_DestroyRuntime(rt);
return;
}


參考資料

關(guān)于作者

唐新華 軟件工程師,歡迎讀者和我取得聯(lián)系。

email: xhsmart@263.net


posted on 2011-07-22 16:07 楊粼波 閱讀(1482) 評(píng)論(1)  編輯 收藏 引用 所屬分類: C++

評(píng)論

# re: 功能強(qiáng)大的JavaScript引擎--SpiderMonkey[未登錄] 2012-10-06 00:06 yt

期待樓主能出更好的博文,關(guān)于js引擎解析的文章太少了!  回復(fù)  更多評(píng)論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲人午夜精品| 国产亚洲精品久久久久婷婷瑜伽| 亚洲第一狼人社区| 免费日韩视频| 欧美精品亚洲精品| 亚洲一区三区电影在线观看| 亚洲一区二区三区在线播放| 国产欧美一区二区在线观看| 久久偷窥视频| 欧美国产一区视频在线观看 | 亚洲女同在线| 国产女人18毛片水18精品| 久久久欧美精品| 蜜臀av在线播放一区二区三区| 亚洲精选91| 亚洲免费在线看| 91久久综合亚洲鲁鲁五月天| 夜夜夜久久久| 国产色爱av资源综合区| 欧美第十八页| 国产精品外国| 亚洲高清久久久| 欧美午夜影院| 欧美激情一区二区| 国产精品网站视频| 亚洲第一福利视频| 国产麻豆91精品| 亚洲激情亚洲| 狠狠干成人综合网| 夜夜夜久久久| 亚洲国产精品ⅴa在线观看 | 亚洲性线免费观看视频成熟| 极品尤物av久久免费看| 一区二区欧美日韩视频| 在线观看中文字幕不卡| 亚洲天堂网在线观看| 最新中文字幕亚洲| 亚洲大片在线观看| 亚洲色诱最新| 亚洲免费观看在线视频| 久久尤物视频| 久久久久国产精品人| 国产精品毛片| a4yy欧美一区二区三区| 亚洲精品一区二区三区婷婷月| 欧美一区二区三区四区高清| 亚洲一线二线三线久久久| 男男成人高潮片免费网站| 久久青草欧美一区二区三区| 国产精品日韩精品欧美在线| 一本色道久久综合精品竹菊 | 久久成年人视频| 亚洲一区国产精品| 欧美日韩美女在线| 亚洲免费大片| 日韩视频免费在线| 欧美不卡视频| 亚洲电影自拍| 亚洲日本中文字幕区| 暖暖成人免费视频| 牛牛国产精品| 亚洲国产成人av| 久久永久免费| 亚洲第一在线视频| 亚洲精品国精品久久99热一| 麻豆精品国产91久久久久久| 欧美国产第一页| 亚洲韩国精品一区| 牛牛国产精品| 亚洲激情一区| 中文久久乱码一区二区| 欧美私人网站| 亚洲男人影院| 玖玖在线精品| 亚洲电影第1页| 欧美高清一区| 中日韩午夜理伦电影免费| 亚洲在线观看免费| 国产欧美一区二区在线观看| 久久国产成人| 亚洲国产精品专区久久| 夜夜嗨av色综合久久久综合网 | 欧美一区二区性| 久久免费视频在线| 91久久亚洲| 国产精品va在线| 久久成人人人人精品欧| 欧美黄色一级视频| 亚洲一区二区三区乱码aⅴ| 国产日韩亚洲欧美精品| 久久综合久色欧美综合狠狠| 亚洲欧洲一级| 久久av免费一区| 亚洲精品少妇| 国产精品一区二区视频| 久久久久久久久久久久久久一区 | 亚洲精品国产精品久久清纯直播| 亚洲欧美国产日韩天堂区| 国产一区二区三区久久悠悠色av | 欧美日韩国产色综合一二三四 | 亚洲精品美女久久久久| 欧美一区二区三区四区在线观看| 在线精品视频一区二区| 欧美香蕉大胸在线视频观看| 久久久777| 亚洲一区三区在线观看| 欧美激情视频网站| 欧美一级在线视频| 亚洲精品一品区二品区三品区| 国产欧美日韩精品专区| 欧美激情免费在线| 久久久久久久波多野高潮日日| 日韩一区二区久久| 老司机一区二区| 国产亚洲人成网站在线观看| 欧美日韩国产首页在线观看| 久久这里有精品视频| 亚洲欧美日韩久久精品| 亚洲精品在线看| 牛夜精品久久久久久久99黑人| 欧美在线999| 亚洲自拍都市欧美小说| 亚洲另类春色国产| 亚洲成色精品| 国产专区欧美精品| 国产日韩av一区二区| 国产精品v片在线观看不卡| 欧美高清不卡在线| 久久在线免费| 久久婷婷av| 久久久久久穴| 久久久免费精品| 欧美一区二区黄色| 午夜日韩在线| 亚洲欧美一区二区三区极速播放| 99国产精品久久| av成人免费| 夜夜嗨av一区二区三区中文字幕| 亚洲精品国产日韩| 亚洲国产婷婷香蕉久久久久久| 亚洲国产第一| 亚洲激情视频| 亚洲精品一区久久久久久| 亚洲欧洲在线视频| 亚洲精品久久久一区二区三区| 亚洲欧洲一区二区三区在线观看| 亚洲成色www8888| 亚洲黄色免费网站| 亚洲日本va午夜在线影院| 亚洲精品欧洲精品| 亚洲作爱视频| 亚洲综合大片69999| 午夜久久美女| 久久久久一本一区二区青青蜜月| 久久久久国产精品www| 麻豆freexxxx性91精品| 欧美精品粉嫩高潮一区二区| 欧美日韩视频在线一区二区 | 一区二区三区鲁丝不卡| 亚洲一级电影| 欧美综合国产| 男女激情久久| 99精品国产一区二区青青牛奶 | 欧美成人蜜桃| 亚洲人成绝费网站色www| 亚洲视频在线观看| 久久激情综合网| 欧美国产日韩免费| 国产精品日韩精品欧美精品| 一区在线免费| 一本色道久久88综合日韩精品| 欧美一区二区大片| 蜜臀久久99精品久久久画质超高清 | 亚洲大片免费看| 在线一区二区日韩| 久久精品亚洲热| 亚洲电影免费| 午夜亚洲视频| 欧美男人的天堂| 国产丝袜一区二区| 亚洲精品三级| 久久精品天堂| 一本久道综合久久精品| 久久久噜噜噜久噜久久| 欧美视频中文字幕在线| 1024成人网色www| 久久国产精品99精品国产| 亚洲在线视频观看| 久久精品国产视频| 欧美性猛交xxxx免费看久久久| 国内精品嫩模av私拍在线观看 | 韩国一区二区三区美女美女秀| 亚洲片在线资源| 久久久精品国产一区二区三区| 日韩天天综合| 麻豆精品91| 樱花yy私人影院亚洲| 午夜亚洲视频| 亚洲免费av片| 免费看的黄色欧美网站|