如何获取 "Invalid chrome URI" 异常的堆栈跟踪?

How to get a stack trace for "Invalid chrome URI" exceptions?

我正在调试一个基于 XUL 的 Firefox 扩展,它已被 Firefox 46 版本破坏。

当我运行扩展时,Browser console显示:

Invalid chrome URI: /

既没有行号也没有堆栈跟踪。

在网络论坛上,I've readChromeBug 可用于此目的。然后,我尝试了最新稳定版的 ChromeBug (1.7.2),但自 10 月以来就没有更新过。 2014,似乎与最新的 Firefox 版本不兼容。

因为扩展是 "old-style",所以我不能使用 Add-on debugger, therefore I used the Browser toolbox,但它不显示异常。

考虑到扩展的行数,在代码中徘徊不是一种选择。知道如何获得堆栈跟踪吗?

当在浏览器控制台中收到此类错误时,您几乎没有得到关于错误原因的信息,很可能错误不在 JavaScript 中,甚至可能不在您的代码。在这种情况下,不可能获得 JavaScript 堆栈跟踪,因为它根本不存在。

这种情况通常是由 XUL 中的问题或 HTML 在打开的弹出窗口或选项卡中使用引起的。您的加载项会打开一个包含 chrome://restclient/content/restclient.html 内容的选项卡。将该文件替换为没有内容的 HTML 文档会使错误消失。

对该文件的内容进行二进制搜索(comment-out/delete 一次搜索文件的一半并测试错误是否仍然存在)到 A) 确认错误存在并且B) 导致错误的原因,导致确定以下行导致错误显示在浏览器控制台(第 197 行)中:

<input class="span5" style="width:-moz-calc(100% - 1em) !important;" type="password" name="password" autocomplete="on" placeholder="Password">

多一点测试表明,当 type 不是 password 时,问题就会消失。将原始 HTML 文档复制到我可以使用 file: URL 轻松访问它的地方,导致在打开文档时浏览器控制台中没有这样的错误。

因此,结论是当从 chrome: URI 加载时,它是 <input type="password"> 的 Mozilla 代码中的错误。

在没有堆栈跟踪的代码中找到无效的 chrome: URI:
如果在 HTML 或 XUL 文件中未发现问题,则有必要查看加载项中使用的 chrome: URI 以查找可能的原因。

chrome: URI 具有一些我们可以利用的属性来追踪此类问题:

  • chrome: URI 通常 是静态的。
  • chrome: URI 通常采用 chrome:\packageName\{content,skin,locale}
  • 格式
  • 您的 chrome.manifest 文件定义了哪些 chrome: URI 对您的 add-on/package.
  • 有效
  • 其他 chrome.manifest 文件定义了哪些 chrome: URI 在您的 add-on/package.
  • 之外有效

所以先看看你的chrome.manifest文件:

content   restclient                content/
resource  restclient                ./

overlay chrome://browser/content/browser.xul chrome://restclient/content/overlay.xul
overlay chrome://navigator/content/navigator.xul    chrome://restclient/content/overlay.xul
style chrome://global/content/customizeToolbar.xul chrome://restclient/content/css/overlay.css

这告诉我们,在您的包中,唯一有效的内部 chrome: URI 将采用 chrome://restclient/content/ 格式,并将引用 content 目录在附加组件的根目录中。

因此,我们现在查找您的附加组件中使用的所有 chrome: URI。为此,grep -nri chrome: * 的命令行是一种简单的方法。 grep 可作为标准实用程序在多个操作系统下使用。在Windows中,我通常从Cygwin中获取。从该命令我们得到:

chrome.manifest:4:overlay chrome://browser/content/browser.xul chrome://restclient/content/overlay.xul
chrome.manifest:5:overlay       chrome://navigator/content/navigator.xul        chrome://restclient/content/overlay.xul
chrome.manifest:6:style chrome://global/content/customizeToolbar.xul chrome://restclient/content/css/overlay.css
content/css/overlay.css:30:  list-style-image: url("chrome://restclient/content/images/icon16.png") !important;
content/css/overlay.css:33:  list-style-image: url("chrome://restclient/content/images/icon16.png") !important;
content/js/restclient.js:51:        i18nStrings = new restclient.StringBundle("chrome://restclient/locale/restclient.properties");
content/js/restclient.main.js:1040:      xslDocument.load("chrome://restclient/content/xsl/XMLPrettyPrint.xsl");
content/js/restclient.main.js:1053:      xslDoc.load("chrome://restclient/content/xsl/XMLIndent.xsl");*/
content/js/restclient.overlay.js:68:    browser.selectedTab = browser.addTab("chrome://restclient/content/restclient.html");
content/overlay.xul:2:<?xml-stylesheet href="chrome://restclient/content/css/overlay.css" type="text/css"?>
content/overlay.xul:7:  <script type="application/x-javascript" src="chrome://restclient/content/js/restclient.js" />
content/overlay.xul:8:  <script type="application/x-javascript" src="chrome://restclient/content/js/restclient.overlay.js" />
content/overlay.xul:23:                    image="chrome://restclient/content/images/icon16.png"
content/overlay.xul:35:              image="chrome://restclient/content/images/icon16.png"
content/overlay.xul:46:              image="chrome://restclient/content/images/icon16.png"
content/overlay.xul:58:              image="chrome://restclient/content/images/icon16.png"/>
modules/StringBundle.js:59: *     new StringBundle("chrome://example/locale/strings.properties");

现在,我们可以并且可能应该手动查看其中的问题,但我们可以通过以下命令快速缩短列表以找到明显的问题:grep -nri chrome: * | grep -v chrome://restclient/content/。这将为我们提供任何 chrome: URI,这些 URI 的格式不是您的附加组件 content 的引用。获得的列表很容易包含有效的 chrome: URI,这些 URI 引用了附加组件之外的文件。所以,我们可能需要做更多的检查。从上面的命令我们得到:

content/js/restclient.js:51:        i18nStrings = new restclient.StringBundle("chrome://restclient/locale/restclient.properties");
modules/StringBundle.js:59: *     new StringBundle("chrome://example/locale/strings.properties");

第一个是 locale chrome: URI。您没有在 chrome.manifest 中指定 locale。因此,它肯定是无效的。查看 content/js/restclient.js 的第 51 行,它在活动代码中。真正用到的时候就失效了

第二种可能性是一个典型的例子chrome: URI。该行以 * 开头,暗示它可能是注释。查看modules/StringBundle.js的第59行,发现是注释

下一步,如果问题还没有被发现,将解决已知的无效 chrome: URI 并测试是否解决了问题。在这种情况下,我们已经知道问题是什么,所以不需要检查。

但是,假设 chrome://restclient/locale/restclient.properties 无效并且 A) 在您的附加组件中没有这样的文件并且 B) 在您的 [=124 中没有定义 locale =] 这意味着如果执行该代码,它将失败。基本上,函数 restclient.i18n 似乎是 dead/bad 代码,应该删除。鉴于该函数是 modules/StringBundle.js 文件的唯一用途,它也可以被删除。显然,如果这是您正在积极从事的工作,那就另当别论了。

在解决这个问题时,我还注意到浏览器控制台中的其他一些错误,您可能应该看看:

21:26:37.975 SyntaxError: test for equality (==) mistyped as assignment (=)?1 chrome://restclient/content/js/bootstrap.js:1557:33
21:26:37.989 TypeError: variable url redeclares argument1 chrome://restclient/content/js/restclient.main.js:376:8

虽然这些不是固有错误,但通常希望在您的附加组件正常运行期间不要在浏览器控制台中显示任何内容。虽然,考虑到 jquery.js 中报告的各种错误,还有哪些错误?