2011-10-04 71 views
7

我有一個工具,類似於JSFiddle的方式,它允許我動態輸入JavaScript並在頁面上運行它。代碼可以是多行,通常會是。動態加載代碼並獲取解析錯誤的行數

不幸的是,如果在我輸入的代碼中存在異常,那麼如果使用eval()運行代碼,則無法獲取異常的行號。

我找到了部分解決方案,這是不是使用

try{ 
eval(code); 
} 
catch(e) { 
processException(e); 
} 

,而不是做這樣的事情:

var s = document.createElement('script'); 
s.appendChild(document.createTextNode(
    "try{\n" + 
    code + 
    "}catch(e){processException(e)}")); 
document.body.appendChild(s); 

現在,如果代碼拋出一個異常,我看堆棧跟蹤(在我的processException()函數)我可以得到異常的行號(在Firefox和鉻,無論如何)。

如果它實際上是一個運行時異常,例如未定義的變量,那就很好。問題是如果有分析錯誤/語法錯誤,例如不匹配的parens或類似錯誤。我什麼也沒得到。

是否有任何瘋狂的解決方法,至少在firefox和chrome上有效?函數對象內腳本標記內的eval是否在eval內?我正在嘗試一切,並沒有找到任何可行的方法。

回答

2

我終於找到了一個合理的解決方案。

首先,我將window.onerror設置爲某個函數。這沒有得到完整的堆棧跟蹤,但會得到一個文件和行號。

然後,我這樣做:

var s = document.createElement('script'); 
s.appendChild(document.createTextNode(
    "var someUniqueGlobalName = function() {\n" + 
    code + 
    "\n};"; 
document.body.appendChild(s); 

請注意,這並不實際運行我的代碼,因爲它只需創建一個函數(在全球範圍內,名稱爲「someUniqueGlobalName」 - 這當然每次我這樣做時,我都會想出不同的名字)。

如果存在語法錯誤,它將被捕獲到window.onerror函數中,並且我可以獲取錯誤類型和行號(當然,我必須從中減去一個,因爲我添加了一行在開始時)。

現在,我未設置window.onerror。

最後,我通過在try/catch塊中調用someUniqueGlobalName()來運行代碼。在這裏,如果存在運行時錯誤,我可以使用行號獲得完整的堆棧跟蹤。

+0

這是一個非常有用的原理。謝謝。 – SystemParadox

1

你可以把它更進了一步,整合的JSLint:https://github.com/douglascrockford/JSLint

這是很簡單..這裏有一個快速測試...

下載:https://raw.github.com/douglascrockford/JSLint/master/jslint.js

jshint_test.html:

<script type="text/javascript" src="jslint.js"></script> 
<script> 

var result = JSLINT("var some = true;\nif (some) {"); 

if (result) 
{ 
    alert('Looking good'); 
} 
else 
{ 
    var error_message = ''; 
    for (i in JSLINT.errors) 
    { 
    var error = JSLINT.errors[i]; 
    error_message += error.reason + ' on line: ' + error.line + ' character: ' + error.character + "\n"; 
    } 
    alert(error_message); 
} 
</script> 

查閱文檔。 JSLINT的第二個參數是一個選項對象..有多個選項。

+0

創意但不是我在找什麼。 – rob

+1

好奇......那麼你在找什麼?這會爲您提供最初請求的解析和語法錯誤。 – Jake

+0

我是在正確之後,而不是Crockford對JS應該是什麼樣子的看法。另外它對我所做的事情來說很笨重,所以更喜歡瀏覽器內置的語法檢查 – rob