史 櫓 吳毅堅 趙文耘
1(復(fù)旦大學(xué)軟件學(xué)院 上海 201203)2(復(fù)旦大學(xué)計算機科學(xué)技術(shù)學(xué)院 上海 201203)3(上海市數(shù)據(jù)科學(xué)重點實驗室 上海 201203)
作為2017年GitHub[1]上最受歡迎的語言,JavaScript這種基于對象的解釋性腳本語言有著諸多靈活的特性,例如它無需提前編譯,變量的數(shù)據(jù)類型也可以改變。這些特性配合瀏覽器事件、HTML DOM、CSS等技術(shù)使得根據(jù)用戶交互動態(tài)改變頁面而無需刷新成為可能,極大地豐富和美化了原本只能提供靜態(tài)顯示功能的網(wǎng)頁。與此同時,越來越多基于JavaScript語言開發(fā)的插件和庫也提高了開發(fā)者編寫效率,深化了所開發(fā)網(wǎng)站平臺的功能。
隨著2013年Node.js[2]的發(fā)布,JavaScript語言可以在非瀏覽器環(huán)境下運行。脫離了瀏覽器環(huán)境束縛的JavaScript不但性能更好,而且可以實現(xiàn)讀寫本地磁盤等傳統(tǒng)瀏覽器中無法達到的功能,吸引了更多的開發(fā)者。根據(jù)TIOBE[3]所統(tǒng)計的數(shù)據(jù),2017年12月份JavaScript在其熱門語言排行榜上排名第六。
然而,隨著JavaScript的逐漸普及和程序規(guī)模的逐漸擴大,許多工程師也意識到其靈活的特性有可能降低它的可維護性和可理解性。由于JavaScript語言中既不存在命名空間的設(shè)計,也不像Java等語言一樣存在包和引入的概念。對于一個網(wǎng)頁來說,其需要的所有JavaScript文件將會被一同載入,互相之間可以隨意訪問,同名函數(shù)或?qū)ο笠矔a(chǎn)生沖突。這些JavaScript語言特征給程序帶來了問題,同時也催生了各種針對JavaScript程序的分析和重構(gòu)工具。
對JavaScript語言的研究在20世紀(jì)90年代已經(jīng)逐步開展,但是學(xué)術(shù)界仍然較缺乏系統(tǒng)的研究綜述,特別是對代碼分析框架、技術(shù)以及應(yīng)用方面。國內(nèi)早期存在JavaScript語言綜述[4],主要僅針對語言特性。近年來,JavaScript研究逐漸受到研究者的關(guān)注,出現(xiàn)了針對JavaScript語言近十余年的分析方法和具體研究問題的綜述,并以時間軸的形式對研究趨勢做了分析[5]。但該綜述研究涉及面很廣,沒有特別關(guān)注JavaScript的代碼分析等軟件開發(fā)和維護問題。Mesbah等[6]針對Web應(yīng)用總結(jié)了近二十年來關(guān)于分析和測試的研究成果和工具,但也不是僅針對JavaScript這種語言,沒有細(xì)化討論其分析方法??梢姡瑢avaScript代碼的分析的現(xiàn)狀認(rèn)知仍需更有針對性的綜述和梳理。
本文的主要貢獻在于,重點收集了自1995年以來與JavaScript相關(guān)的國內(nèi)外文獻,根據(jù)所發(fā)表期刊、會議的級別和主題等標(biāo)準(zhǔn)精選了291篇,并對其中與JavaScript代碼分析最相關(guān)的158篇文獻進行了系統(tǒng)的整理,分析了歷史上和近年來JavaScript代碼分析的主要研究方向、應(yīng)用,并對相關(guān)研究現(xiàn)狀和趨勢進行了討論。
根據(jù)系統(tǒng)文獻回顧(SLR)方法,本文對國外文獻整理時使用Dblp[7]計算機文獻數(shù)據(jù)庫進行綜合檢索,對JavaScript代碼分析技術(shù)這一問題進行研究。截止2017年底,該數(shù)據(jù)庫共收錄超過400萬篇目計算機文獻,涉及到超過3萬種會議和3萬種期刊,時間跨度從1995年至今,在國內(nèi)外具有較高的權(quán)威性。具體文獻內(nèi)容以及引用關(guān)系從IEEEExplorer、ACMdl、Springer等網(wǎng)站中獲取。
使用JavaScript作為關(guān)鍵字,共有782篇文獻資料被檢索到,其中會議論文524篇,期刊論文140篇,其余書籍、非正式出版物或數(shù)據(jù)資料不列入研究范圍。根據(jù)統(tǒng)計,包含2篇及以上JavaScript文獻的會議82個,文獻共計346篇;期刊24種,文獻共計71篇。從研究領(lǐng)域上考慮,按照中國計算機學(xué)會的分類,A類和B類的會議37個,文獻共計198篇;期刊6種,文獻共計23篇。其中軟件工程和設(shè)計語言領(lǐng)域最多,共計148篇;其次是網(wǎng)絡(luò)與信息安全領(lǐng)域,共計40篇;此外交叉和綜合領(lǐng)域共計19篇。由于JavaScript語言的使用與網(wǎng)絡(luò)息息相關(guān),本文主要選擇前兩個領(lǐng)域A類與B類的文獻資料作為研究對象,對JavaScript代碼分析技術(shù)這一問題進行研究。
以上188篇文獻在經(jīng)過初步閱讀并進行篩選后被分為九個類別,如表1所示。由于本文研究的是代碼分析技術(shù),因此對綜述、性能、測試、底層、功能擴展和安全領(lǐng)域不進行進一步分析,而是主要考察語言特性、分析框架方法、維護和重構(gòu)的89篇文獻。
表1 研究文獻分類
根據(jù)技術(shù)背景和經(jīng)驗,本文還指定了多個額外的關(guān)鍵詞進行搜索,從其他會議和期刊中補充了65篇文獻,如表2所示。
表2 擴展關(guān)鍵字查詢
續(xù)表2
在國內(nèi)期刊方面,本文在中國知網(wǎng)上以JavaScript作為關(guān)鍵詞,對國內(nèi)計算機類核心期刊進行查詢時共搜索到103篇論文,其中57篇論文運用JS技術(shù)或者AJAX技術(shù)實現(xiàn)功能或開發(fā)應(yīng)用,20篇涉及JavaScript代碼混淆、惡意腳本檢測等安全問題,8篇與底層設(shè)計、瀏覽器尤其是移動端或嵌入式瀏覽器有關(guān),9篇為AJAX、JavaScript、DOM等內(nèi)容的綜述,4篇對AJAX等功能進行了擴展,以及1篇提出了Web前端性能的整體解決方案。僅有4篇論文與語言特性或程序分析框架方法有關(guān),在本文中進行了整理和綜述。
為了更好地對總計158篇的JavaScript代碼分析技術(shù)相關(guān)文獻進行研究,本文提出以下幾個研究問題并在后面的章節(jié)中進行回答:
RQ1:當(dāng)前JavaScript代碼的分析方法和框架有哪些?有什么特點和缺陷?
RQ2:當(dāng)前針對JavaScript語言的代碼分析研究主要集中在哪些方面?
RQ3:針對JavaScript語言的研究呈現(xiàn)怎樣的現(xiàn)狀和趨勢?
JavaScript代碼中數(shù)據(jù)流和控制流的跟蹤和分析是掌握整個程序中各個部分之間關(guān)聯(lián)的重要條件,也是獲取程序中函數(shù)關(guān)系的重要步驟。而采用不同的分析方法和框架亦會產(chǎn)生不同的結(jié)果從而影響開發(fā)者對程序的評估以及問題的檢測。在對文獻的研究中,本文發(fā)現(xiàn),JavaScript代碼的分析方法主要有靜態(tài)分析、動態(tài)分析和混合分析幾類,并會在接下來的小節(jié)對方法和框架進行闡述,以回答第一個研究問題。
靜態(tài)分析是在不執(zhí)行目標(biāo)代碼的情況下,通過分析代碼本身實現(xiàn)對數(shù)據(jù)流和控制流的掌控。其優(yōu)點是與實際執(zhí)行的環(huán)境無關(guān),不受實際使用時給出的參數(shù)影響,從而可以發(fā)現(xiàn)實際使用中不會或很少出現(xiàn)的程序異常。同時,因為無需實際解釋和執(zhí)行代碼,尤其是不需要自動或人工輸入?yún)?shù),靜態(tài)分析的速度更快,效率更高。靜態(tài)分析的缺點在于對一些動態(tài)數(shù)據(jù)類型或動態(tài)綁定等涉及使用動態(tài)特性的代碼可能產(chǎn)生誤判或漏判。近年來相關(guān)研究工作中主要使用了以下幾種基于靜態(tài)分析的綜合框架。
T.J.Watson Libraries for Analysis,簡稱WALA[8],是2006年IBM公司T.J.Watson實驗室在研究過程中初步建立起靜態(tài)開源分析框架。WALA框架面對Java語言,可以實現(xiàn)類型分析、指針分析、調(diào)用圖構(gòu)建、數(shù)據(jù)流分析、切片等多種靜態(tài)分析。針對JavaScript語言的特性,WALA開發(fā)了將JavaScript代碼標(biāo)準(zhǔn)化的工具JS_WALA[9]并在此基礎(chǔ)上實現(xiàn)了部分基礎(chǔ)分析功能,其中包括基于指針分析的調(diào)用圖構(gòu)造分析以及基于域的調(diào)用圖構(gòu)造分析。前者由于需要保證其充分性,在使用了大量框架的JavaScript程序中效率較低。而后者提供了一種較為近似的處理方式,犧牲充分性以提高效率。需要注意的是,JS_WALA在GitHub上的源代碼已經(jīng)四年沒有更新過,這不僅意味著很可能難以直接從開發(fā)者處獲取支持,更意味著此框架在未來幾年可能無法適應(yīng)JavaScript語言本身的更新與發(fā)展。
SAFE[10]是2012年由韓國科學(xué)技術(shù)研究院針對JavaScript所遵循標(biāo)準(zhǔn)ECMAScript[11]5.0版本所開發(fā)的開源靜態(tài)分析工具。此分析工具在Java和JavaScript的抽象語法樹AST分析工具Rhino[12]的基礎(chǔ)上進行了擴展,并使用Java和Scala[13]語言對生成的AST進行處理以方便轉(zhuǎn)化為中間語言進行后續(xù)分析。但是,該工具不支持eval語句、JavaScript 嚴(yán)格模式,以及一些標(biāo)準(zhǔn)內(nèi)建對象,對with語句也只是部分支持。隨后,陸續(xù)有論文基于或以SAFE為參照對JavaScript進行靜態(tài)分析,例如LSA分析[14-15]、Web API請求靜態(tài)檢測[16]等。2016年,SAFE更新至2.0版本,為原本的分析器加入了基于HTML的圖形化展示工具,并將向輕量化的JavaScript網(wǎng)絡(luò)應(yīng)用分析程序發(fā)展,逐步支持錯誤檢測、DOM建模、jQuery分析、事件處理等功能。
2015年,兩種框架的設(shè)計者聯(lián)合發(fā)表了一篇論文[17]。不同于JS_WALA中所提供的兩種極端方案,論文中設(shè)計了由用戶自行調(diào)整充分性和效率性所占的比例的針對大規(guī)模JavaScript程序的靜態(tài)分析框架,并在平均調(diào)用數(shù)的準(zhǔn)確性和覆蓋度兩方面與JS_WALA和SAFE進行了比較,為研究者提供了更多的選擇。
與綜合分析框架不同,一些部分分析的工具也被廣泛使用。例如Esprima[18]作為靜態(tài)分析的第一步,在Node.js環(huán)境下將ECMAScript轉(zhuǎn)換為抽象語法樹AST,并支持最新標(biāo)準(zhǔn)[19]。在許多針對JavaScript程序分析的論文中,作者并沒有直接使用完整的分析框架,而是選擇生成抽象語法樹之后根據(jù)自身的需求或條件進行有目的地分析從而獲得更高的靈活度和效率,例如數(shù)據(jù)類型失配檢測[20]等。因此,在某些特定范圍的分析中可以選擇在抽象語法樹的基礎(chǔ)上直接開展有針對性的研究而無需應(yīng)用整個靜態(tài)分析流程,從而減少不必要的時間成本。
此外,還有部分靜態(tài)分析工具主要用于代碼檢查。例如谷歌、雅虎等著名企業(yè)使用的JSHint[21],可以對用戶所編寫的JavaScript代碼進行語法檢查,通過已知的問題特征發(fā)現(xiàn)隱性類型轉(zhuǎn)換、變量泄露等問題。類似的工具還有ESHint[22]、JSLint[23]、Plato[24]等。文獻[25]等對這些靜態(tài)檢查工具在實際JavaScript程序中的應(yīng)用情況也進行了調(diào)查,而文獻[26]等使用各種靜態(tài)方法檢測實際系統(tǒng)中的問題。
如果將靜態(tài)分析比作軟件測試中的白箱測試,動態(tài)分析就類似于黑箱測試。與靜態(tài)分析相反,動態(tài)分析將分析的過程放在代碼的實際運行環(huán)境中,通過直接跟蹤代碼的執(zhí)行過程實現(xiàn)獲取數(shù)據(jù)流、控制流等信息的目的。在JavaScript中存在大量的動態(tài)特征,例如將字符串轉(zhuǎn)化為代碼執(zhí)行的eval語句,使用字符串變量直接調(diào)用對象屬性的表示方法等。這些信息需要在運行過程中確定而不能僅僅依靠分析源代碼得到結(jié)果,因此無法完全使用靜態(tài)分析實現(xiàn)。相對于靜態(tài)分析框架,盡管與動態(tài)分析相關(guān)的內(nèi)存抓取[27]、自動化測試[28]、用戶交互捕捉[29]、代碼推薦[30]、提高覆蓋率[31]等技術(shù)或方法常有發(fā)表,但是動態(tài)分析框架的實現(xiàn)則相對較少。
Jalangi[32]是近年來較為重要的JavaScript動態(tài)分析工具。自2013年Jalangi以論文形式發(fā)表以來,根據(jù)谷歌學(xué)術(shù)統(tǒng)計的引用數(shù)量已有130篇,并且近年來出現(xiàn)的使用動態(tài)分析研究JavaScript具體問題,例如動態(tài)對類型一致性[33]、數(shù)據(jù)結(jié)構(gòu)遍歷[34]、動態(tài)流[35]等中也多有涉及。而在2013年對JavaScript進行動態(tài)分析的相關(guān)文獻僅有2篇關(guān)于JavaScript動態(tài)行為和動態(tài)特性的研究。Jalangi作為一種重量級的動態(tài)分析框架,既可以使用記錄-重現(xiàn)技術(shù)進行離線模式分析,也可以在瀏覽器中使用影子內(nèi)存技術(shù)直接進行在線分析,同時提供了大量常用的分析模板供研究者選擇。在Jalangi不足方面,由于其對源代碼進行了修改和添加,實際執(zhí)行的修改后的JavaScript程序不僅在體積上遠(yuǎn)遠(yuǎn)超出原有大小,代碼執(zhí)行速度上也會受到一定影響。目前,Jalangi1.0版本已經(jīng)停止更新,Jalangi2[36]項目不再使用記錄-重現(xiàn)技術(shù)并整合了部分動態(tài)代碼檢查工具,目前支持ECMAScript5.1版本。
2017年8月份GitHub上出現(xiàn)了動態(tài)分析框架Iron.js[37]。該框架的機制與Jalangi類似,同樣是記錄代碼運行時的數(shù)據(jù)并通過監(jiān)聽器對數(shù)據(jù)進行跟蹤和處理。目前,該框架的版本為0.3,仍處于測試階段并且沒有相關(guān)的發(fā)表文獻。
混合分析即是把靜態(tài)分析與動態(tài)分析相結(jié)合,利用兩種分析方式的優(yōu)點,填補他們的不足。例如,動態(tài)分析可以對靜態(tài)分析難以企及的JavaScript動態(tài)特性進行處理,而靜態(tài)分析則可以填補測試用例和輸入?yún)?shù)設(shè)計所帶來的覆蓋率問題,從而使分析結(jié)果更完整、可信度更高。
在DBLP數(shù)據(jù)庫上搜索JavaScript和blended analysis、hybrid analysis或static dynamic analysis共有13篇論文。其中文獻[38-39]等提出了使用動態(tài)分析跟蹤執(zhí)行軌跡和動態(tài)加載的代碼并進行靜態(tài)污點分析的框架JSBAF;文獻[40]等提出了DOM敏感的變更影響混合分析工具TOCHAL;文獻[41]等提出了混合安全分析方法JSA等。此外,基于混合分析的JavaScript類型分析工具JSFox[42]發(fā)表在2017年ICSE會議上。該工具使用Esprima和JS_WALA進行靜態(tài)類型分析,借助Jalangi進行動態(tài)類型分析并將靜態(tài)分析中不易發(fā)現(xiàn)的調(diào)用關(guān)系或動態(tài)特征等動態(tài)分析的結(jié)果作為補充依據(jù),與靜態(tài)類型分析結(jié)果相結(jié)合。在這些論文中,研究者分別使用靜態(tài)和動態(tài)分析框架并合理組合,取得了更為科學(xué)的實驗信息和結(jié)果。
為回答第二個研究問題,本文對158篇論文考察后發(fā)現(xiàn)針對JavaScript語言的代碼研究主要集中在以下幾個方面。
JavaScript的語言特性在帶來靈活編程風(fēng)格的同時,也給系統(tǒng)的維護和代碼的分析帶來了諸多問題。因此,部分學(xué)者針對其語言特性不斷進行研究,例如文獻[43]對JavaScript語言特性的實際使用情況進行了研究,文獻[39]為JavaScript語言特性設(shè)計了混合分析框架,文獻[44]對語言特性在實際開發(fā)中引入和應(yīng)用的情況進行了經(jīng)驗研究等。此外還有數(shù)篇有關(guān)異步交互等動態(tài)行為的案例研究與分析[45-51]。本節(jié)將按照不同的語言特性對這些研究進行分類敘述。
3.1.1 類型分析
JavaScript作為弱類型語言,變量不僅定義時無需指定變量類型,甚至可以在執(zhí)行中隨意修改類型,這為類型推斷等帶來了麻煩。
許多研究者針對JavaScript的動態(tài)類型這一特征帶來的問題,設(shè)計或擴展出新的類型系統(tǒng)。例如支持參數(shù)化類型和能夠簡化類型書寫的TeJeS[52],保證互聯(lián)網(wǎng)應(yīng)用中類型安全的TS*[53],為網(wǎng)絡(luò)沙盒屬性提供基于編碼和確認(rèn)功能的ADsafety[54],支持嵌套保護和流敏感類型的DJS[55],修復(fù)JavaScript對象布局問題的SJS[56]及其擴展[57],為移動設(shè)備設(shè)計的輕量級Typed JS[58],基于復(fù)雜格結(jié)構(gòu)的TAJS[59],平攤類型系統(tǒng)[60]及其他類型系統(tǒng)研究[61-65]等。此外,文獻[66]對靜態(tài)類型系統(tǒng)進行了研究,闡述了Flow或typeScript等是如何提升軟件質(zhì)量,降低錯誤數(shù)量的。
類型檢查和類型推斷是另一類重要的類型分析,例如前文提到的類型一致性分析工具TypeDevil[27]和混合類型分析工具JSFox[42]。此外還有針對數(shù)字類型進行快速推斷并以此提升編譯器效率的靜態(tài)分析工具RATA[67],量化了動態(tài)類型檢查代價并擴展了原生類型檢查的Checked Load[68],基于規(guī)則約束并支持undefined等類型的類型分析算法TypeCastor[69],以及數(shù)篇通過動態(tài)和靜態(tài)結(jié)合方法進行類型分析和推斷的研究文獻[70-72]。
其他有關(guān)類型的研究也具有參考的價值,例如:文獻[73]基于對象的結(jié)構(gòu)和行為推斷類型確定動態(tài)耦合;文獻[74]在TAJS基礎(chǔ)上設(shè)計了基于類型的依賴分析;文獻[75]提出了類型細(xì)化以提高靜態(tài)分析的準(zhǔn)確性;文獻[76]使用動態(tài)分析方法對JavaScript隱式類型轉(zhuǎn)換進行了經(jīng)驗研究;文獻[77]設(shè)計了基于類型感知的符號測試等。
3.1.2 回調(diào)函數(shù)
回調(diào)是JavaScript代碼中另一個重要的語言特性。匿名回調(diào)、回調(diào)嵌套等在JavaScript項目中均存在廣泛使用,同時也對代碼的可讀性和可維護性造成了不良影響。
文獻[78]對138個JavaScript項目的超過500萬行代碼中的回調(diào)情況按照同步異步回調(diào)、命名匿名回調(diào)、嵌套回調(diào)等類別提出了分類方法并進行了研究,發(fā)現(xiàn)其中大多數(shù)函數(shù)均存在嵌套的情況,超過一半的是異步回調(diào),并且在客戶端項目中出現(xiàn)較多。同時,帶參數(shù)的回調(diào)函數(shù)中有43%為匿名函數(shù)。此外,論文還分析并比較了錯誤優(yōu)先回調(diào)、Async、Promise三種解決回調(diào)函數(shù)所帶來的復(fù)雜性問題的方案。
文獻[79]針對嵌套回調(diào)導(dǎo)致代碼難以理解和難以回調(diào)的問題設(shè)計了Sync/CC庫,通過應(yīng)用Continuation和Aspects的方法幫助開發(fā)者在維持回調(diào)依賴關(guān)系的同時,同步地處理嵌套回調(diào)。
3.1.3 其他特性
一些零散的其他特性,例如綁定、閉包、eval函數(shù)、類對象等也被許多學(xué)者所研究。
關(guān)于綁定和閉包,文獻[80]針對移動平臺上的嵌入式函數(shù)對象所涉及的閉包問題進行了研究,并設(shè)計了實時棧以處理這一問題。關(guān)于eval函數(shù),文獻[81]對JavaScript網(wǎng)絡(luò)應(yīng)用中該函數(shù)的使用進行了研究,文獻[82]提出了半自動eval函數(shù)移除工具。在對類對象的研究中,文獻[83]使用靜態(tài)方法對遺留系統(tǒng)中的類依賴進行了識別,文獻[84]開發(fā)了Eclipse插件進行類維護和理解,文獻[85-86]使用靜態(tài)分析將JavaScript程序中對類的使用進行了分類,并提出了針對遺留系統(tǒng)代碼進行類檢測的策略。此外,文獻[87]提出了對匿名函數(shù)的分析和命名工具。
代碼壞味道(bad smell)是代碼中存在潛在問題的信號。文獻[88]在1999年提出了22種針對面向?qū)ο笳Z言的壞味道,例如重復(fù)代碼、過長函數(shù)等。JavaScript代碼中也存在類似的問題。
文獻[89]對互聯(lián)網(wǎng)環(huán)境下JavaScript應(yīng)用所存在壞味道的研究[90-91]進行了總結(jié),歸納了13種壞味道,例如:閉包壞味道、過多局部變量、過長鏈?zhǔn)秸{(diào)用、回調(diào)嵌套、繼承壞味道等,并開發(fā)了自動檢測工具JSNOSE。該工具對11個Web應(yīng)用項目的壞味道檢測準(zhǔn)確率達到了93%。該項研究成果被后續(xù)研究多次引用,是有關(guān)代碼壞味道研究的重要成果之一。
文獻[92]依據(jù)JSNOSE研究中多個JavaScript類庫,例如jQuery的代碼風(fēng)格手冊中所提出的代碼壞味道,選擇了單行過長、函數(shù)參數(shù)過多、變量重復(fù)指派、switch-case過多等12個壞味道對JavaScript服務(wù)端的5種應(yīng)用共計537個版本進行了研究。同時,作者也對1 484位JavaScript工程師進行了調(diào)查采訪,獲取了他們對不同壞味道的重視程度。這一研究主要的貢獻在于其方法針對的是服務(wù)端應(yīng)用而非客戶端應(yīng)用。
文獻[93]將遺傳算法用于JavaScript壞味道檢測。他們將JSNOSE等發(fā)現(xiàn)的已知壞味道案例作為訓(xùn)練集訓(xùn)練壞味道檢測模型,從而能從其他JavaScript代碼中發(fā)現(xiàn)壞味道。在對9個JavaScript網(wǎng)絡(luò)項目的實驗中,他們將遺傳算法的壞味道檢測結(jié)果與JSNOSE工具所分析的結(jié)果進行了對比,達到了92%的準(zhǔn)確率,可見將遺傳算法引入壞味道檢測這一方法在將來可能能夠成為檢測問題的有效切入點。
文獻[94]將動態(tài)類型改變作為一種性能相關(guān)的JavaScript代碼壞味道進行了研究,提出JavaScript能夠動態(tài)改變類型這一特性會導(dǎo)致編譯器優(yōu)化失效,從而產(chǎn)生性能問題。因此,他們將其列作壞味道進行分析,開發(fā)了JSweeter工具對這一問題進行檢測。在對Octane項目進行的應(yīng)用研究中,該工具檢測到了46個問題,其中19個被后續(xù)修復(fù),說明了工具的有效性。
及時準(zhǔn)確的代碼重構(gòu)能夠提高系統(tǒng)的可擴展性和可維護性,發(fā)現(xiàn)并解決潛在問題。在文獻中有以下幾類有關(guān)重構(gòu)的研究。
文獻[95-96]對JavaScript的重構(gòu)進行了研究,提出了以指針分析為基礎(chǔ),對重命名、封裝屬性、提煉模塊三種重構(gòu)內(nèi)容進行查找和重構(gòu)的框架。該作者在另一篇關(guān)于半自動重命名重構(gòu)的研究[97]中提出了一套的類型推斷系統(tǒng),以半自動方式進行重命名重構(gòu)。
文獻[98]針對JavaScript遺留系統(tǒng)中與類結(jié)構(gòu)近似的代碼能否向ECMAScript6[99]新標(biāo)準(zhǔn)所提供的類語法進行遷移重構(gòu)這一問題進行了調(diào)查和分析。文獻[100]列出了異步回調(diào)的使用環(huán)境,并嘗試以ECMAScript6中的Promise對其進行重構(gòu)。該工具與文獻[101]提出的針對nodeJS風(fēng)格的異步回調(diào)向Promise重構(gòu)工具Due相比,多完成了235%的重構(gòu)任務(wù)。文獻[102]針對耦合和命名沖突設(shè)計開發(fā)了將代碼自動重構(gòu)為ECMAScript6中module的方法。這三篇論文均涉及到JavaScript最新標(biāo)準(zhǔn)ECMAScript6相關(guān)特性的應(yīng)用以及將遺留系統(tǒng)遷移至新標(biāo)準(zhǔn)的重構(gòu)嘗試。
隨著JavaScript的不斷發(fā)展,許多新的特性和方法被開發(fā)出來以解決實際問題,例如Promise對象通過定義reject和resolve等方法處理異步調(diào)用時不同狀態(tài),用于異步計算;通過創(chuàng)建Promise實例將回調(diào)函數(shù)的嵌套狀態(tài)解除,解決回調(diào)地獄(callback hell)問題,提高代碼可維護性和可讀性。文獻[103]還對JavaScript項目中使用Promise出現(xiàn)的錯誤進行了分類,并設(shè)計了Promise圖以檢測這些錯誤。
模塊化分析是代碼分析的另一項重要內(nèi)容,高內(nèi)聚、低耦合的模塊化開發(fā)能夠提高系統(tǒng)的可擴展性和可維護性。傳統(tǒng)的JavaScript語言并不強調(diào)模塊化特性,缺乏模塊化管理手段。JavaScript程序一般直接以文件作為程序?qū)ο?如變量、方法)進行管理。在早期JavaScript程序規(guī)模比較小并且僅用于少量的Web頁面前端處理的情況下,這種特性并不會產(chǎn)生太大的問題。然而,隨著JavaScript程序日益復(fù)雜,規(guī)模日益增大,這種不利于代碼維護和管理的開發(fā)方式的缺陷也逐步顯現(xiàn)出來。因此,近年來JavaScript開發(fā)社區(qū)對其模塊化問題也做了大量的研究和實踐。
文獻[104]針對JavaScript缺乏模塊管理這一問題,設(shè)計了一種能夠支持安全的進行增量開發(fā)的模塊系統(tǒng)。作者希望通過擴展JavaScript現(xiàn)有語法以實現(xiàn)這一系統(tǒng),并給出了詳細(xì)的語法設(shè)計,但是并沒有給出具體的實現(xiàn)。與之類似的研究還有文獻[105-106]提出的基于SAFE框架的模塊系統(tǒng),并從不支持eval等角度與Kang的設(shè)計進行了對比,給出了一些具體的設(shè)計問題,例如,如何處理eval函數(shù)、全局變量沖突等。文獻[107-108]針對JavaScript中的模塊模式進行了探討。由于沒有原生的模塊系統(tǒng),模塊模式就成為了JavaScript實現(xiàn)模塊化變成的手段之一。文獻[109]提出了基于擴展的WebIDL語言中JavaScript庫API誤用的深度檢測方法,同時也設(shè)計實現(xiàn)了針對可復(fù)用性和可維護性的模塊化檢測工具,并嘗試與SAFE2相結(jié)合。
為了解決JavaScript模塊化不強的問題,近幾年也不斷有模塊管理和前端MVC框架被開發(fā)出來,提供模塊化編程功能。例如以AMD標(biāo)準(zhǔn)[110]開發(fā)的RequireJS[111],可以實現(xiàn)對JavaScript文件的模塊化加載功能,使得原本同時加載的文件可以按照依賴關(guān)系逐步載入,降低了系統(tǒng)的耦合。在前端MVC方面,謝珩[112]等設(shè)計了一種MVC在前端的實現(xiàn)方式。而AngularJS[113]作為流行的前端MVC框架,包含模塊化、依賴注入等各種功能。它通過聲明各種概念,大大簡化所需編寫的代碼量,提高了項目的可維護性和開發(fā)效率。該框架在不斷迭代升級中逐漸成熟,目前已經(jīng)發(fā)展到第五版。近年來針對該框架的研究也日益增多,例如文獻[114-115]對460個項目中AngularJS使用情況進行了調(diào)查,統(tǒng)計了其中最受歡迎的幾大特征,如自定義接口、依賴注入和二路綁定等,同時也指出了所存在的性能問題及其原因。此外也有一些基于該框架進行的研究或開發(fā)的工具,例如模型驅(qū)動在AngularJS項目中的應(yīng)用[116],基于AngularJS的實時網(wǎng)絡(luò)社交應(yīng)用[117]等。另外,由于commonJS等模塊管理類庫以及ECMAScript6中module等特性的出現(xiàn),開發(fā)者有了新的標(biāo)準(zhǔn)化的模塊化方法。
為了回答第三個研究問題,本文首先對所研究的291篇論文以時間為考量進行了統(tǒng)計,如圖1所示。從總數(shù)上看,在JavaScript語言發(fā)明的10年后,也就是2005年后相關(guān)論文數(shù)量開始穩(wěn)步增加,并且在正值20周年和ECMAScript6標(biāo)準(zhǔn)發(fā)布的2015年出現(xiàn)了井噴的情況。整體上看,研究工作隨著JavaScript的逐步普及呈穩(wěn)步上升趨勢。從分布上看,有關(guān)JavaScript的應(yīng)用研究逐年減少,反之分析框架方法和語言特性的研究呈上升趨勢并且逐漸穩(wěn)定,證明研究重心逐步從以JavaScript作為開發(fā)語言設(shè)計應(yīng)用轉(zhuǎn)移到對其程序本身的特性和行為進行分析。
圖1 文獻總數(shù)和比例趨勢
同時,關(guān)于目前的研究現(xiàn)狀,291篇文獻中近三年來,即2015年到2017年的文獻共計98篇。如圖2所示,近三年來文獻數(shù)量最多的三類是分析框架方法、語言特性和安全。其中分析框架方法方面,盡管分析方法多種多樣,但是從分析框架的角度考慮,靜態(tài)分析仍然是主流。15篇論文使用靜態(tài)分析,5篇論文使用動態(tài)分析,2篇論文使用混合分析。其次是JavaScript的安全性問題,不論是信息流的監(jiān)控和限制,還是信息泄露的檢測,抑或是第三方資源的引用安全問題,都是目前安全工程師和研究者們關(guān)注的重點。第三是語言特性方面,針對類型分析的論文共計8篇,JavaScript類的論文4篇,異步行為論文2篇,回調(diào)論文1篇。在這些論文中,雖然類和類型分析的研究論文數(shù)量最多,但隨著新的JavaScript標(biāo)準(zhǔn)和新框架的出現(xiàn),研究中涉及到異步問題、回調(diào)等的內(nèi)容也呈逐漸上升的趨勢。由于相關(guān)技術(shù)在實踐中的逐步推廣,針對這些新方法、新特性的研究,可能成為后續(xù)的研究熱點之一。
圖2 近三年文獻類別分布
本文系統(tǒng)收集了1995年以來針對JavaScript的研究論文,對JavaScript代碼分析技術(shù)所使用的分析框架按照靜態(tài)分析、動態(tài)分析和混合分析進行了綜述,整理了當(dāng)前研究中常用的JavaScript代碼分析框架和方法,并進一步按照語言特性、代碼壞味道、代碼重構(gòu)、模塊化等四種研究目的對JavaScript代碼分析技術(shù)的研究成果進行了解讀。最后,依據(jù)文獻資料對近年來JavaScript研究的現(xiàn)狀和趨勢進行了梳理,并希望借此為廣大研究者對JavaScript代碼分析技術(shù)和方向以及所使用的工具帶來宏觀的認(rèn)識。
隨著ECMAScript6標(biāo)準(zhǔn)的逐步普及,有關(guān)該標(biāo)準(zhǔn)中包含的新方法與新特性以及遺留系統(tǒng)向該標(biāo)準(zhǔn)遷移正在逐步地實施之中,可能會出現(xiàn)新的研究點。不論是嵌套回調(diào)函數(shù)重構(gòu)為Promise函數(shù)[100],還是匿名函數(shù)參數(shù)重構(gòu)為箭頭函數(shù),在這些改變的背后都有可能存在著潛在的代碼可讀性、健壯性或性能問題,將來值得研究者們隨時予以關(guān)注。