我正在调试一个基于XUL的Firefox扩展,该扩展已被Firefox 46版本破坏。
当我运行扩展时,浏览器控制台显示:
Invalid chrome URI: /
既没有行号也没有堆栈跟踪。
在网络论坛上,我读到ChromeBug可以用于此。然后,我尝试了ChromeBug的最新稳定版本(1.7.2),但自2014年10月以来一直没有更新,似乎与最近的Firefox版本不兼容。
因为这个扩展是"老式"的,所以我不能使用插件调试器,所以我使用了浏览器工具箱,但它不显示异常。
考虑到扩展的行数,在代码中漫游不是一种选择。知道我怎么能得到堆栈跟踪吗?
当在浏览器控制台中获得这种类型的错误时,您几乎没有得到导致错误的信息,很可能错误不在JavaScript中,甚至可能不在代码中。在这种情况下,不可能获得JavaScript堆栈跟踪,因为它根本不存在。
这样的事情通常是由打开的弹出窗口或选项卡中使用的XUL或HTML中的问题引起的。您的加载项将打开一个包含内容的选项卡chrome://restclient/content/restclient.html。用一个没有内容的HTML文档代替该文件可以消除错误。
使用该文件内容的二进制搜索(一次注释/删除文件的渐进式半部分,并测试错误是否仍然存在)到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加载时,这是Mozilla的<input type="password">
代码中的一个错误。
在没有堆栈跟踪的代码中查找无效的chrome:
URI:
如果在HTML或XUL文件中没有发现问题,则有必要查看附加组件中使用的chrome:
URI,以查找可能的原因。
chrome:
URI具有一些属性,我们可以利用这些属性来跟踪这样一个问题:
chrome:
URI通常是静态的chrome:
URI通常采用chrome:\packageName{content,skin,locale}
格式- 您的chrome.manifest文件定义了哪些
chrome:
URI可以对您的加载项/包有效 - 其他chrome.manifest文件定义了哪些
chrome:
URI可以在加载项/包之外有效
因此,首先查看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/
格式,并将引用加载项根目录中的内容目录。
因此,我们现在查找附加组件中使用的所有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)chrome.manifest.中没有定义locale
,这意味着如果执行该代码,它将失败。基本上,函数restclient.i18n
是死代码/坏代码,应该删除。考虑到该函数是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中报告的各种错误,还有什么呢?