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