查找破坏 IE 的 ECMAScript/JavaScript 错误

Posted

技术标签:

【中文标题】查找破坏 IE 的 ECMAScript/JavaScript 错误【英文标题】:Find IE-breaking ECMAScript/JavaScript errors 【发布时间】:2011-05-15 02:56:39 【问题描述】:

我在一个相对庞大的 ECMAScript 代码库 (> 60,000 LOC) 上工作,我们往往会为我们可怕的朋友 Internet Explorer(尤其是 6 和 7)检测错误而费力。

目前,我被一个问题困扰了 3 天,我的 RIA 在 Google Chrome、Firefox 3.6、Opera 和 Internet Explorer 8 中呈现良好,但在 IE7 模式下运行 Internet Explorer 8(或一个真正的 IE-7)。

我的问题是:如何识别会在 IE7 中产生错误的代码?

通常我依赖 JSLint 并且我倾向于捕捉通常的嫌疑人(尾随逗号,我讨厌你),但在这种特殊情况下,我刚刚对我的所有代码重新运行了一个 linter,包括源代码和最小化代码,它不会产生我通常的嫌疑人。所以我想我错误地引入了 IE 不喜欢的东西(谁知道呢,也许我疯了,在某处使用了 Array.map 而不是 dojo.map?)它在我的脸上炸开了,产生了很好的错误消息对我一点帮助都没有(“[object object]”和“is null”在不应该出现的地方,所以我认为上游存在错误,该错误以静默方式失败并阻止创建此对象)。

我曾尝试查看 Google Closure Linter,但它并没有产生任何特别之处,而且我认为 Google Closure Compiler 也不会成为我的救星。是否有任何工具(命令行、Web 服务或其他)可以像模拟 IE 一样解析/运行代码,以便我们得到相应的错误?

感谢任何提示。

编辑:感谢您迄今为止在尝试解决我的问题方面提供的帮助,但我真正要问的是是否有工具可以进行此类检查,这意味着针对特定浏览器验证功能集和语法。在我看来,这是 JS 世界中严重缺乏的东西(对于 FF 或 Chrome 而言,显然它们的调试器更有帮助)。

EDIT2:我今天(3 天后)最终找到了问题的根源,方法是检查两个分支之间的所有代码更改,并意识到问题实际上已经存在,但之前从未检测到,并通过更旧的更改返回到缩小混乱范围并最终在所有地方添加控制台日志,直到我遇到故障点(上帝感谢 emacs 的正则表达式支持,可以将日志添加到每一行......很重但有效......)。不过有趣的事实是:IE 吞下了一条错误消息,该消息应该显示在 try catch 块中,最初是捕获源问题,然后重新抛出它。仍然不知道为什么,但如果没有,那会更容易找到,因为它是为此目的而设计的,以防万一它坏了。诡异的。可能不喜欢重投的深层次。

我将保留这个问题,因为目前没有实际问题的答案。

【问题讨论】:

当您在 IE8 中以良好的旧 IE7 模式运行并打开调试控制台时,您是否选中了“错误中断”按钮,以便指出错误发生的位置? JSLint 和 Closure 编译器更多是关于语法问题,而不是 Browser X 不支持 Y 方法。 @epascarello:是的,除了它指向我们的一个 throw 语句,然后通过堆栈跟踪显示我们抛出的内容并不能确定任何内容。另外,它似乎并不特定于该文件:如果我更改在引导程序中启动的文件的顺序,它将在某个地方失败,无论哪个是第一个。我知道 JSLint 和 Closure 不这样做,但通常与浏览器相关的主要问题是 IE7 的尾随逗号,它们确实有助于捕捉到这一点。当然,不会对其他任何事情有太大帮助。 @epascarello:实际上,如前所述,它指出了一个对象(实际上是对象的包命名空间)为空的行(因为在这种情况下,但不应该是。但是之前没有抛出其他错误......除了控制台在这个特定错误之前仍然只显示一个红色的“[object object]”消息,但没有中断它)。 【参考方案1】:

你可以试试Microsoft Script Debugger,或者Internet Explorer Developer Tools。

有关 IE 8 与旧版本可能不同的完整列表,请咨询:

Internet Explorer 8 Readiness Toolkit (官方名单) 尤其是DOM Improvements javascript in Internet Explorer 8 (John Resig 的帖子)

另请参阅Web Bug Track 了解可能的怪癖。

作为最后一点,在每一行都写console.log 可能会帮助你很难找到一个特定的错误,但考虑到你应该为模块编写单元测试的代码量。这是确保您的应用程序在不同的输入和条件下实际运行的唯一方法。

【讨论】:

如前所述,IE 提供的消息在这种情况下并没有太大帮助。这些来自集成调试器,并被报告是因为基本上一个对象不存在(它应该存在的地方),这意味着在此之前可能遇到了另一个错误,该错误以静默方式失败。 查看我的更新。我很确定您的问题与 DOM 相关。 @galambalazs:在 RIA 渲染的这个阶段不太可能,因为在我们仍然引导和加载依赖项时错误开始发生。但这是可能的,我会看看你的名单,然后回复你。谢谢。 @galambalazs:绝对不是 DOM 相关的,它发生在 DOM 更改之前,除了动态依赖加载(注入脚本节点)。 还有一点需要注意的是,没有对 60k 行代码进行单元测试是徒劳的。【参考方案2】:

你可以试试 IE8 调试器,正如@galambalazs 建议的那样; IE6 时代的旧调试器通常没用。

我一直使用的低级技术是在我的 Javascript 源代码的大部分周围添加我自己的 try/catch 块,以缩小错误源的范围。通过反复调整 try/catch 块,您可以通过源代码进行“二分搜索”以定位导致异常的代码。您可能会发现一些代码在 Firefox 中是无害的,但 IE 的解释器认为这些代码是错误的。 (公平地说,通常IE的严格性是有道理的,而Firefox的松懈行为确实是不可取的。)

换句话说,您将从您怀疑的 Javascript 源开始,或者您可能会对所有包含的 .js 文件执行此操作:

// top of Javascript source file foo.js
try 
  // ... all the code ...
 catch (x)  alert("Error in foo.js: " + x); 

现在,如果您加载页面并收到该警报,那么您就知道错误在 foo.js 中的某个地方。因此,您将其分成两半:

// top of foo.js
try 
  // ... half the code, roughly ...

catch (x)  alert("Error in first half of foo.js: " + x); 
try 
  // ... the rest of the code ...
 catch (x)  alert("Error in second half of foo.js: " + x); 

重复该过程,您最终会发现问题。

【讨论】:

真的不期待超过 60,000 行的 b-tree 搜索,老实说 :) 经过十次左右的迭代,您可能会开始怀疑问题出在哪里。 window.onerror 会让你在没有 try/catch 块的情况下更接近。 window.onerror = function (msg, url, line) alert("Error on line "+ line); @Pointy:与url 参数一起,在 IE 7 及更低版本中非常不可靠,但我在 IE 8 上的所有经验(并且我已经编写了一个 onerror 堆栈跟踪器)告诉我这是固定的,除了极少数情况下,它是一条偏离标记的行。 @Andy E 是的,我同意 IE8(大部分)在这方面都已修复,但问题是关于 IE7 或 IE7 模式。如果 IE8 不模拟特定的 IE7 功能(我从未尝试过),那么您是对的,那将是一种更快的方法。但是,直接依靠 IE8 调试器可能会更快!

以上是关于查找破坏 IE 的 ECMAScript/JavaScript 错误的主要内容,如果未能解决你的问题,请参考以下文章

在 IE11 中包装 flex 项目被破坏

IE9 - 添加和删除 DOM 元素会破坏父 keydown 事件

使用 png 填充图像移动 Raphael 路径,而不破坏 IE 中的图像或相对于元素移动图像?

IE游览器强制广告问题

使用 Oracle 的正则表达式功能来查找双元音序列,例如。 ‘ie’, ‘ee’, ‘oa’

JavaScript 在IE中查找插件