鄭大勇,王艷輝(通信作者)
(通化師范學(xué)院 吉林 通化 134002)
HTML5是超文本標(biāo)記語言(hyper text markup language,HTML)的第5次重大修改,2014年10月由萬維網(wǎng)聯(lián)盟(World Wide Web Consortium,W3C)完成標(biāo)準(zhǔn)制定。HTML5的設(shè)計(jì)目的是在移動設(shè)備上支持多媒體,它是網(wǎng)頁前端的標(biāo)準(zhǔn)書寫語言,是構(gòu)建Web的重要工具。現(xiàn)如今,HTML5是Web中的核心語言,是網(wǎng)站開發(fā)技術(shù)人員必須要掌握的一項(xiàng)技術(shù)。隨著移動互聯(lián)網(wǎng)的發(fā)展越來越多,行業(yè)巨頭正不斷向HTML5靠攏。除蘋果、微軟、黑莓之外,谷歌的Youtube已部分使用HTML5;Chrome瀏覽器宣布全面支持HTML5;Facebook則不遺余力地為HTML5進(jìn)行著病毒式傳播。
CSS3是層疊樣式表(cascading style sheets,CSS)技術(shù)的升級版本,于1999年開始制訂,2001年5月23日W3C完成了CSS3的工作草案。在網(wǎng)頁制作時采用層疊樣式表技術(shù),可以有效地對頁面的布局、字體、顏色、背景和其他效果實(shí)現(xiàn)更加精確的控制。只要對相應(yīng)的代碼做一些簡單的修改,就可以改變同一頁面的不同部分,或者頁數(shù)不同的網(wǎng)頁外觀和格式。CSS3語言開發(fā)是朝著模塊化方向發(fā)展的,把它分解為一些小的模塊,更多新的模塊也被加入進(jìn)來。CSS3主要包括盒子模型、列表模塊、超鏈接方式、語言模塊、背景和邊框、文字特效、多欄布局等模塊。
JavaScript是一種直譯式腳本語言,也是一種動態(tài)類型、弱類型、基于原型的語言,內(nèi)置支持類型。它的解釋器被稱為JavaScript引擎,為瀏覽器的一部分,廣泛用于客戶端的腳本語言中,最早是在HTML(標(biāo)準(zhǔn)通用標(biāo)記語言下的一個應(yīng)用)網(wǎng)頁上使用,用來給HTML5網(wǎng)頁增加動態(tài)功能。1995年,由Netscape公司的Brendan Eich,在網(wǎng)景導(dǎo)航者瀏覽器上首次設(shè)計(jì)實(shí)現(xiàn)而成。因?yàn)镹etscape與Sun合作,Netscape管理層希望它外觀看起來像Java,因此取名為JavaScript。
HTML5和JavaScript之間的依賴主要有兩大類:1)從HTML5到JavaScript文件的鏈接。鏈接的依賴源于HTML5文檔所在的代碼,HTML5文檔中包含對JavaScript文件的引用實(shí)現(xiàn)動態(tài)效果。2)HTML5文件中的事件監(jiān)聽器。JavaScript作為序事件驅(qū)動的語言,對事件的監(jiān)聽是必不可少的。事件監(jiān)聽就是為了讓計(jì)算機(jī)隨時能夠發(fā)現(xiàn)用戶與網(wǎng)頁的交互動作,計(jì)算機(jī)發(fā)現(xiàn)事件發(fā)生了,從而執(zhí)行程序員預(yù)先編寫的一些程序。
定義CSS3規(guī)則中最常用的CSS選擇器是類選擇器,類選擇器允許以一種獨(dú)立于文檔元素的方式來指定樣式。該選擇器可以單獨(dú)使用,也可以與其他元素結(jié)合使用。一個類選擇器標(biāo)識為模型中的一個依賴項(xiàng)。
JavaScript到HTML5之間可以通過文檔對象作為依賴項(xiàng)的,這樣的引用用于獲取HTML5元素的句柄執(zhí)行事件綁定、DOM操作等。如果引用沒有存在,它會導(dǎo)致JavaScript出現(xiàn)錯誤。
JavaScript到CSS3之間的依賴項(xiàng)是JavaScript和HTML5之間依賴關(guān)系的擴(kuò)展。研究中看到JavaScript可以使用文檔訪問HTML5元素對象,一旦使用JavaScript代碼獲得了對任何元素的引用,就可以將一個CSS3類賦給HTML5元素。
用于定義CSS3規(guī)則的2個常見CSS選擇器,是類選擇器和id選擇器。類選擇器在HTML5中會被標(biāo)識為對CSS3的依賴項(xiàng),另一個依賴項(xiàng)是由id選擇器生成的。這種依賴性在CSS3規(guī)則中使用id選擇器訪問HTML5中的具體唯一元素。
在本文范圍內(nèi),沒有確定CSS3和JavaScript任何相關(guān)的依賴關(guān)系。盡管存在一些依賴項(xiàng),如從JavaScript使用文檔訪問HTML5元素對象,再將一個CSS3類賦給HTML5元素,但這已經(jīng)在JavaScript對CSS3的依賴中覆蓋了。
對于HTML5的解析,使用了Jsoup解析器。Jsoup是一款Java的HTML解析器,這是一個流行的Java庫。Jsoup解析器支持所有最新的HTML5標(biāo)簽,能夠從URL、文件或字符串解析HTML5。Jsoup解析器將HTML5解析為文檔對象模型(document object model,DOM),用于在HTML5文檔中表示對象(節(jié)點(diǎn)),也為DOM訪問和遍歷提供了一個非常簡單的應(yīng)用程序接口(application programming interface,API)。API中基于正則表達(dá)式的選擇器,使其非常靈活。Jsoup解析器可生成一個解析樹,但是DOM是通過API作為“Document”對象公開的。雖然Jsoup解析器提供了這么多漂亮的功能,但一個主要的缺點(diǎn)是它沒有跟蹤行號。因此,一個基于Java的Matcher引擎自定義模塊,用于跟蹤行號和列號十分重要。
根據(jù)用以分析的源目錄,將所有的HTML5文件根據(jù)文件擴(kuò)展名提取,一旦所有的HTML5文件被識別,每個文件均可使用Jsoup解析器解析。對每個文件提取文件對象,最簡便的方法,如:getAllElementIds、getAllElementClasses、getScriptLinks和getEventHandlers,均實(shí)現(xiàn)了遞歸遍歷元素對象并提取所需的數(shù)據(jù)。從這些方法中,提取每個HTML5文件可以得到以下數(shù)據(jù):1)使用所有“id”屬性;2)使用所有“類”屬性;3)鏈接到所有相關(guān)的CSS3樣式表;4)鏈接到所有相關(guān)的媒體資產(chǎn)(圖像、視頻、音頻等);5)所有相關(guān)JavaScript文件的鏈接;6)所有通過事件處理程序引用的方法。
此外,解析器允許檢查存儲為Parse Error的語法錯誤,上述數(shù)據(jù)可用于每個文件、每個引用文件(CSS3文件、JavaScript文件或資產(chǎn)文件)被檢查是否存在和路徑有效性。如果沒有找到任何文件,則產(chǎn)生FileNotFound依賴錯誤。之后,每個關(guān)聯(lián)的CSS3文件和JavaScript文件被解析和分析其他依賴關(guān)系。
基于此項(xiàng)目的目的,使用CSS3的現(xiàn)代Web應(yīng)用程序。為了避免解析缺陷并提取準(zhǔn)確的選擇器列表,研究使用了一種用于CSS3的SAC解析器。SAC解析器是一個解析CSS3文件的Java庫,支持CSS1、CSS2和CSS3。SAC解析器接受CSS3文件文本作為輸入,并生成DOM,這個解析器的優(yōu)點(diǎn)是它允許附加一個錯誤處理程序來跟蹤解析每個規(guī)則生成的錯誤。與每個HTML5文件相關(guān)的所有CSS3文件,均可使用此解析器處理。一旦HTML5解析階段完成,所有有效的關(guān)聯(lián)CSS3文件被識別,每個文件被傳遞到CSS3解析器。對于每個CSS3文件,可以提取以下數(shù)據(jù):1)引用id列表;2)定義類的列表。一旦獲得了這些數(shù)據(jù),靜態(tài)分析器就會使用這些信息分析基于類和id引用的依賴項(xiàng)。
本文選擇了Nashorn引擎,以解析JavaScript。Nashorn引擎是由Oracle開發(fā)的JavaScript引擎,在之前與Java8及以上版本捆綁在一起,它的速度與Chrome的V8引擎相當(dāng)。與每個HTML5文件相關(guān)的所有JavaScript文件,均使用這個解析器處理。一旦HTML5解析階段完成了所有有效的相關(guān)JS文件,那么每個文件均會傳遞給JS解析器。對于每個JS文件,可以提取以下數(shù)據(jù):1)引用id列表;2)引用類的列表;3)定義的所有方法的方法簽名。對象的位置將存儲每個文件的所有上述信息。
一旦收集了所有相關(guān)文件中的數(shù)據(jù),就會將其與依賴項(xiàng)進(jìn)行比較當(dāng)他們出現(xiàn)的時候。如,在JavaScript文件中識別id列表時,這些id會同時與HTML5文件中的現(xiàn)有id進(jìn)行比較。如果一旦發(fā)現(xiàn)錯誤,它就會立即存儲在Results對象中,稍后再進(jìn)行檢索顯示,CSS3文件處理的情況也類似。當(dāng)找到依賴項(xiàng),而不會導(dǎo)致運(yùn)行時錯誤,作為警告存儲在Results對象中。根據(jù)詳細(xì)級別,用戶可以選擇查看詳細(xì)信息。
基于規(guī)則的分析,有助于幫助用戶過濾掉一次一個類別的結(jié)果和視圖。錯誤作為錯誤分類的一部分進(jìn)行討論,其輸出結(jié)果是根據(jù)標(biāo)志值進(jìn)行篩選的,并且內(nèi)部計(jì)算也是一樣的。這樣的原因是需要避免任何依賴和錯誤的計(jì)算分析被忽視。該標(biāo)志支持的值有:1)ParseError,將過濾掉結(jié)果,只顯示遇到的解析錯誤,同時解析HTML5、CSS3或JavaScript。2)ReferenceError,將過濾掉結(jié)果以顯示引用錯誤,引用錯誤可以是各種類型,如不存在的類、不存在的id和不存在的函數(shù)。3)FileNotFound,將過濾掉結(jié)果,顯示未找到文件的錯誤。值得注意的是,此處也檢查遠(yuǎn)程文。4)警告,將過濾結(jié)果,只顯示警告,以此來警告那些不會導(dǎo)致運(yùn)行時錯誤的依賴項(xiàng)。
獨(dú)立的命令行工具和安裝在集成開發(fā)環(huán)境(integrated development environment,IDE)上的插件是大多數(shù)靜態(tài)分析工具有2種類型,但有著不同的用途。獨(dú)立的命令行工具可以集成到構(gòu)建工具鏈或持續(xù)集成工具,而集成插件可以服務(wù)于IDE中交互式實(shí)用程序,幫助開發(fā)人員在編寫代碼時處理缺陷。此工具也采用了類似的方法。當(dāng)瀏覽器接收到一個請求網(wǎng)頁時,它首先獲取HTML5文件,一旦文件被檢索,它就會啟動解析HTML5文檔,HTML5標(biāo)簽被轉(zhuǎn)換成DOM節(jié)點(diǎn)在“內(nèi)容樹”。然后,從各種樣式中解析樣式數(shù)據(jù)源碼,包括CSS3樣式表和內(nèi)聯(lián)樣式標(biāo)簽,以及內(nèi)容樹樣式信息被合并生成“渲染樹”。經(jīng)過一個“布局”過程,最終在瀏覽器上繪制,這個繪制的圖層便是用戶在瀏覽器上所看到的內(nèi)容。靜態(tài)分析工具流程,如圖1所示?;趦?nèi)部解析優(yōu)化技術(shù),HTML5在獲取相關(guān)腳本文件時,文檔解析可能會停止,也可能不會停止和解析。一般流程解釋了瀏覽器如何加載網(wǎng)頁。
圖1 靜態(tài)分析工具流程
靜態(tài)分析工具的主要目的是識別HTML5、CSS3和JavaScript之間的依賴關(guān)系,為了達(dá)到此目的,本文使用不同的解析器來解析這些語言并跟蹤依賴關(guān)系。網(wǎng)頁渲染流與網(wǎng)頁相關(guān)的JavaScript獲取和解析流程,如圖2所示。
圖2 網(wǎng)頁渲染流與網(wǎng)頁相關(guān)的JavaScript獲取和解析流程
Web應(yīng)用中的HTML5文件是通往整個代碼庫的大門,靜態(tài)分析工具還通過構(gòu)建一個HTML5列表,來分析指定目錄中的文件并從那里移動。此外,跟蹤與每個依賴項(xiàng)相關(guān)的元數(shù)據(jù),以幫助開發(fā)人員查找并盡快修復(fù)缺陷。元數(shù)據(jù)包括源文件、行號、列號和依賴項(xiàng)類型。該工具的次要功能包括:提供詳細(xì)的輸出,輸出結(jié)果在JavaScript對象表示法(JSON)和純文本格式,顯示JSON結(jié)果的HTML查看器,基于規(guī)則的分析,修復(fù)建議和集成插件開發(fā)。
對于開發(fā)人員來說,跟蹤代碼庫的語法及跨HTML5、JavaScript和CSS3堆棧的依賴項(xiàng)均是開發(fā)過程中的挑戰(zhàn)。開發(fā)人員手動檢查工具和運(yùn)行情況時,大量的由于語法依賴而產(chǎn)生的缺陷容易被忽視,從而出現(xiàn)人為錯誤。此外,往返代碼編輯器和瀏覽器之間,增加了開發(fā)時間和成本,這些因素將會對整個開發(fā)團(tuán)隊(duì)的聚合導(dǎo)致嚴(yán)重的后果并影響最終產(chǎn)品。通過創(chuàng)建模型和工具的解決方法,識別和快速解析HTML5、CSS3和JavaScript的依賴項(xiàng),以提高Web開發(fā)人員的開發(fā)效率和生產(chǎn)力。從設(shè)計(jì)的角度來看,工具也可以進(jìn)一步改進(jìn),使之成為實(shí)時的,而不是即時工具的當(dāng)前實(shí)現(xiàn)。