博客 / 詳情

返回

?Hanjst漢吉斯特改進+enSafeExpression安全表達式等

Hanjst漢吉斯特模版語言及模版引擎,近期持續改進升級。
這次改進主要是增加了對安全輸出表達式兼容,由於涉及到對軟件開發過程中的效率和軟件運行效率的平衡和取捨,所以多寫了幾句,以描述這個權衡利弊對思考過程。距離上次更新:?Hanjst漢吉斯特升級:+showImageAsync及性能改進等 ( https://ufqi.com/blog/hanjst-... ),時間過得並不算長,希望Hanjst早日成熟而穩定下來。

1. 問題及背景

Hanjst 模版語言解析引擎在編寫時,啓用了JavaScript的 strict mode ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode ),對程序語句執行嚴格對語法檢查,因此如果書寫不嚴格會偶爾拋出異常錯誤警告來。之所以這麼要求,使用JavaScript對strict mode,是希望Hanjst漢吉斯特能夠用在一些關鍵領域和苛刻崗位,將異常錯誤消滅在程序編寫階段。

讓異常在“編譯時”發生,進而得到解決,屬於編程語言方面對準編譯型。這本是好事,因為Hanjst 除了用在普通的資訊網站,也會用在電商、金融等領域,對其進行苛刻對語法檢查,是必需的步驟。

然而,這也有弊端,就是開發時比較耗費時間,需要考慮各種情況,反覆測試各種情景下的軟件行為,無意會加大開發成本。比如常見的 strict mode下的報錯:未定義變量和訪問對象為undefined。報錯信息在 Hanjst裏有較人性化的顯示輸出,參考:漢吉斯特Hanjst+更新升級:error reporting, innerLoop和loadingLayer ,https://ufqi.com/blog/hanjst-...  。

如果因為對接的系統處於非關鍵領域和苛刻崗位,對於往復出現的這種變量未定義或者訪問undefined對象,能不能進行一些主動兼容?這次就是考察這個問題。

2. 解決思路及方法

對這個問題的考察,大致兩種方法:1)在模版編譯時,去掉 JavaScript對strict mode,使之不再做嚴格對檢查,從而避免類似未定義變量和訪問undefined對象;2)第二種思路是在保持 strict mode對前提下,做一些局部的微調,使之能夠兼容這些低級錯誤,也保留對其他語法對嚴格檢查。

在大的方向上去掉Strict mode顯然是不行的,這會從本質上動搖Hanjst用在關鍵領域和苛刻崗位的定位。這一點不應拿來討論。啓用strict mode,進行編譯時語法檢查,對嚴肅軟件是必需的。

在JavaScript中,探測一個變量是否被定義,是一件容易的事,使用類似 typeof 對指令,可以判斷某個變量是否被定義。如果對每一個變量在輸出前都做這樣的檢查,顯然陷入了“一個人有病,全國人吃藥?”的非理智狀態,這也是之前的嘗試被阻止的原因之一。
因此如果要啓用針對變量的探測,需要有某種機制來感知已經被定義了的變量。

另外,如果不使用 JavaScript eval等危險性較高對函數,如何去感知某個字符串所代表對變量是否被定義了?使用內置對象 Function構建匿名函數嗎?如果匿名函數的話,其單獨的變量作用域與變量實際運行環境又有顯著的不同,該如何操作?

第三,在模版語言中,我們允許對象的屬性訪問,這類對象,可能是運行時環境的全局變量,也可能是局部變量;這類對象既可能是一維的Hash數據list,還可能還多位的Hash嵌套,可能存在第一維的數據對象是已經被定義的,而第二維、第三維是未定義的,而此時如果是未定義的,就有可能拋出異常來。

待問題進一步地發散為:
1)繼續啓用Strict mode,
2)在1)的情況下,實現對未定義變量和未定義對象對訪問兼容;
3)儘量不要使用高危函數,如 eval;
4)保證2)都情況下,不能不分情況的對所有變量進行兼容操作;
5)需要區分是全局變量,還是局部變量,各種情況最好都能兼容;
6)需要區分一維對象和多維對象,各種情況最好都能兼容。

經過一番艱難地探索,在嘗試尋求魚和熊掌兼得的情況下,採取如下措施:
1)使用 typeof 生成待執行的變量是否被定義的JavaScript語句;
2)新增環境變量賦值語句的list,用以檢測某個變量是否顯式地被定義;
3)使用 window.hasOwnProperty 探測某個全局變量是否被定義;
4)使用遞歸方式拆解多維數據對象,如, $aList[$ak1][$ak2][$ak3] .

基於以上分析在 Hanjst.js 中新增 _enSafeExpression 函數用於對待輸出對變量及對象進行安全性檢查。

3. 樣例演示

{$a=1}  –> 類似的語句被登記為該變量已經被顯式地聲明;

{\$a}  –>  ((typeof $a == ‘undefined’) ? ” : \$a) , 輸出 $a 對語句如果探測到沒有被定義,將被改寫為三目運算符的表達式;

$aList[$ak1][$ak2][$ak3] –> $aList[$ak1], $aList[$ak1][$ak2] , 將待輸出對三維數據分別逐級拆解,形成待探測的兩個變量/對象,再分別予以構建使用三目運算符的表達式,形成由頂部到底部的逐層檢測,大致為:
((typeof $aList[$ak1] == ‘undefined’) ? ” : ((typeof $aList[$ak1][$ak2] == ‘undefined’) ? ” :$aList[$ak1][$ak2][$ak3]))

更多維的數據對象,也依此類推。 

4. 其他

版本號升至 v1.7, +其他一些細微的優化調整,

一個簡單地問題細究起來,居然一點都不簡單,紙上得來終覺淺,絕知此事要躬行。一個小任務,變量輸出前進行主動安全性檢查,居然嘮嘮叨叨地寫了差不多2000字。

畢竟,Hanjst漢吉斯特在追求平衡的藝術,追求極致而完美。

….


?Hanjst漢吉斯特 是一種基於JavaScript的模板語言及模版解析引擎,她運行在客户端或服務器端。

?Hanjst漢吉斯特 能夠表述邏輯控制,能夠實現與服務器端模版語言相同的強大功能。

  • Hanjst當完全在客户端解析時,節省服務器端計算資源;
  • Hanjst模板語言獨立,不與服務器端資源做任何綁定;
  • 純粹的MVC,層間數據用JSON格式傳遞;
  • 常見模板語言功能全支持,附帶複雜而強大的JavaScript編程能力;
  • 無學習成本,直接使用JavaScript書寫模板語言;
  • ….

Hanjst is a JavaScript-based templating language and parsing engine that runs on both the client-side and/or server-side.

Hanjst can express logical controls and achieve the same functionalities as the server-side templating languages.

  • Hanjst’s Run-time in client-side, reduce computing render in server-side;
  • Hanjst is Language-independent, not-bound with back-end scripts or languages;
  • Totally-isolated between MVC, data transfer with JSON;
  • Full-support template tags with built-in logic and customized JavaScript functions;
  • No more tags languages to be learned, just JavaScript;
  • ….

    兩天來,連續創作兩篇,在寫blog的歷史上,也是少有的行為。同期寫就的另一篇: 寫寫?存款利率貸款利率和負利率 , https://ufqi.com/blog/captial... 。

http://ufqi.com/blog/hanjst-ensafeexpr-updt/
-R/x12SX
https://ufqi.com/news/list.932.html

user avatar flymon 頭像 zhangxishuo 頭像 b_a_r_a_n 頭像 william_wang_5f4c69a02c77b 頭像 tufeiyuan_5d9f0a380c30e 頭像 tempest_619c7f9d4e321 頭像 513928731 頭像 bupthly 頭像 xiaohuoche 頭像 xiaodaigua_ray 頭像 taoqun 頭像 wuyuedexingkong 頭像
35 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.