2011-10-04 74 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