神秘的“脚本错误”。在 Chrome 和 Firefox 中用 JavaScript 报告

IT技术 javascript firefox google-chrome error-handling
2021-01-26 00:48:50

我有一个脚本可以检测我网站上的 Javascript 错误并将它们发送到我的后端进行报告。它报告遇到的第一个错误、假定的行号和时间。

编辑以包括文档类型:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:fb="http://www.facebook.com/2008/fbml">

...

<script type="text/javascript">
//<![CDATA[
// for debugging javascript!
(function(window){
    window.onerror = function(msg, url, ln) {
        //transform errors
        if (typeof(msg) === 'object' && msg.srcElement && msg.target) {
            if(msg.srcElement == '[object HTMLScriptElement]' && msg.target == '[object HTMLScriptElement]'){
                msg = 'Error loading script';
            }else{
                msg = 'Event Error - target:' + msg.target + ' srcElement:' + msg.srcElement;
            }
        }

        msg = msg.toString();

        //ignore errors
        if(msg.indexOf("Location.toString") > -1){
            return;
        }
        if(msg.indexOf("Error loading script") > -1){
            return;
        }

        //report errors
        window.onerror = function(){};
        (new Image()).src = "/jserror.php?msg=" + encodeURIComponent(msg) + "&url=" + encodeURIComponent(url || document.location.toString().replace(/#.*$/, "")) + "&ln=" + parseInt(ln || 0) + "&r=" + (+new Date());
    };
})(window);
//]]>
</script>

由于这个脚本,我非常清楚我网站上发生的任何 javascript 错误。最大的罪犯之一是“脚本错误”。在第 0 行。在 Chrome 10+ 和 Firefox 3+ 中。Internet Explorer 中不存在此错误(或可能称为其他错误?)。

更正 (5/23/2013):这个“脚本错误,第 0 行”错误现在出现在 IE7 和其他版本的 IE 中。可能是最近 IE 安全补丁的结果,因为此行为以前不存在。

有谁知道这个错误是什么意思或导致它的原因是什么?它发生在我整个页面加载的 0.25% 左右,占报告错误的一半。

6个回答

“脚本错误”。当异常违反浏览器的同源策略时,Firefox、Safari 和 Chrome 中会发生这种情况- 即当错误发生在托管在当前页面域之外的域上的脚本中时。

此行为是有意为之,以防止脚本将信息泄漏到外部域。举个例子说明为什么这是必要的,想象一下意外访问evilsite.com,它提供了一个带有 的页面<script src="yourbank.com/index.html">(是的,我们将该脚本标记指向 html,而不是 JS)。这将导致脚本错误,但该错误很有趣,因为它可以告诉我们您是否已登录。如果您已登录,则错误可能是'Welcome Fred...' is undefined,而如果您未登录,则可能是'Please Login ...' is undefined沿着这些路线的东西。

如果 evilsite.com 为前 20 名左右的银行机构执行此操作,他们就会很清楚您访问了哪些银行网站,并且可以提供更有针对性的网络钓鱼页面。(当然,这只是一个例子。但它说明了为什么浏览器不应该允许任何数据跨越域边界。)

我已经在最新版本的 Safari、Chrome 和 Firefox 中对此进行了测试 - 他们都这样做。IE9 没有——它把 x-origin 异常和同源异常一样对待。(而且 Opera 不支持 onerror。)

来自马口:在将异常传递给 onerror() 时检查来源的 WebKit 源以及检查.

更新(2011 年 10 月 21 日)跟踪此问题Firefox 错误包含指向激发此行为的博客文章的链接。

更新 (12/2/14):您现在可以通过在脚本标签上指定crossorigin属性并让服务器发送适当的CORS HTTP 响应标头,在某些浏览器上启用完整的跨域错误报告

您会认为有人会说“由于同源策略,远程脚本抛出了一个隐藏的错误”,而不是让您想知道出了什么问题,嗯?...
2021-04-01 00:48:50
小更新。当页面通过 file:// 加载并且脚本通过 eval() 运行时,它也会在本地发生。次要用例,但仍然:)
2021-04-01 00:48:50
谢谢你。我想澄清一下。我总是从我的页面中包含的脚本中看到详细的错误消息。例如,如果我从 google 的 CDN 中包含 jQuery 并使用它来操作我页面上不存在的元素,我会收到一个指向 google CDN 的 onerror。您是说“脚本错误”吗?正在发生是因为远程脚本抛出异常?
2021-04-04 00:48:50
@broofa 这是否意味着如果我在我的域上托管 jquery 而不是使用 Google 的 CDN,我会变得更好?
2021-04-08 00:48:50
经过一番调查,我注意到Script Error.如果用户安装了 Safari 扩展(可能与 Firefox 插件相同),该扩展也会发生错误注入 JavaScript 代码
2021-04-11 00:48:50

对于将来会遇到这个问题的人的更新:broofa 的答案是正确的,并且没有解决方法。

显然,其他人偶然发现了这个限制,并且为 Firefox 提交了一些请求修复的错误Bug 69301和 WebKit:Bug 70574

好消息是,随着 Firefox 13 的发布,Firefox 已经解决了该错误。这就是您使用它的方式:

<script src="http://somremotesite.example/script.js" crossorigin>

crossorigin相当于crossorigin=anonymous并告诉浏览器不发送凭据的情况下执行脚本的 CORS 提取

您必须确保使用Access-Control-Allow-Origin与请求域匹配的 HTTP 标头值发送脚本,例如,

Access-Control-Allow-Origin: http://myhomesite.example
Access-Control-Allow-Origin: *

否则浏览器将取消加载脚本

对于apache:

Header set Access-Control-Allow-Origin "*"

(并参阅其他 Web 服务器的CORS 示例。)

如果您使用 PHP 发送脚本:

header('Access-Control-Allow-Origin', 'http://myhomesite.example');

我已经测试过了,它按预期工作。来自 script.js 的所有错误都将被window.onerror处理程序捕获,并带有消息、文件和行的详细信息。

WebKit 错误尚未修复,但已提出补丁(并使用相同的解决方案)。希望修复程序将很快发布。

有关 CORS 的更多信息,请访问:http : //enable-cors.org/

假设我们要监控 mysite.com/index.php 中的 JS 错误,其中包含来自外部方(例如 API 提供商的服务器 apiprovider.com/api.js)的 JS 文件;在这种情况下,我们无权访问该服务器,因此我们无法添加“Access-Control-Allow-Origin”标头。有没有办法获取源自 api.js 的错误消息?
2021-03-18 00:48:50
重新 webkit。如果你的意思是这个,它看起来现在已经解决了:bugs.webkit.org/show_bug.cgi?id=70574
2021-04-03 00:48:50
2021-04-08 00:48:50

这个花了很多时间才弄明白。

我们做了很多事情来尝试解决它,包括通过 Ajax 将整个文档正文转储回我们的服务器以尝试解决它。

我仍然不确定是什么导致了“脚本错误”。(顺便说一句,这就是它在我们的 Ajax 记录器中的显示方式)在 Firefox 中,但在 Chrome 中,我们能够将其缩小到......

击鼓...

谷歌浏览器的自动翻译功能。

许多说英语的人可能甚至不知道这个功能,但为了测试它,我想访问一个使用 Chrome 的非英语网站。或者更好的是,如果您深入研究 Chrome 选项,则可以更改浏览器语言。将其更改为非英语内容,重新启动浏览器,然后访问英语站点。

您应该会看到顶部的栏,询问您是否希望 Chrome 为您翻译页面。

无论如何,在我们的案例中,翻译器导致了问题,因为它将脚本标记注入到您的文档正文中,并且(在这里猜测)使用某种基于 JS 的系统将内容发送到 Google 的服务器并让他们翻译它。

即使控制台中的错误是未引用的东西,发送到 window.onerror 的消息是“脚本错误。”。

无论如何,有一种治疗方法。

http://googlewebmastercentral.blogspot.com/2007/12/answering-more-popular-picks-meta-tags.html

<meta name="google" content="notranslate"/>

这将做两件事(据我们所知,也许更多?):

a) 禁止翻译栏在 Chrome 中弹出。

b) 通过 translate.google.com 禁用页面翻译。

无论如何,在我们的情况下,这解决了大量的“脚本错误”。我们遇到的问题。

请原谅这篇文章中的拼写错误,我仍然在 Chrome 中使用非英语模式写这篇文章,而且拼写检查器没有设置为英语 ;) 是时候切换回来了。

享受!

直接原因可能是翻译脚本是从与网页不同的域运行的,并且onerror(至少在 Firefox 中)在这种情况下只会说“脚本错误”。
2021-03-28 00:48:50

由于百分比较低,您可以假设他们不是普通用户。可能有用户脚本、书签的用户,甚至可能只是在你网站上弄乱控制台。拥有一个页面的整个 HTML 可以帮助测试这个理论。以及完全错误。它应该给你一个网址,它总是一样的吗?该行是真的 0 还是只是未定义?

我认为在 onerror 中设置默认值不是一个好主意,并且 0 可能来自parseInt(ln || 0)错误不在页面上的情况(请参见上面的示例)。

添加 if 以查看该行是否在 JavaScript 中已知以忽略这些错误(因为它们可能不是来自您自己的代码)或在服务器端代码中单独处理它们,imo 会更好.

=== 编辑 === 到:http : //www.xavierm02.net/AZE/ 安装 user.js 文件(我在 Chrome 上做了,但它也应该在 Firefox 上工作)。然后在同一浏览器上打开 html 页面。它会告诉你错误(我只改变了向服务器报告的那部分,它写在页面上)。以 0 作为行号。

将您的行替换为(new Image()).src = "/jserror.php?msg=" + encodeURIComponent(msg) + "&url=" + encodeURIComponent(url) + "&ln=" + parseInt(ln) + "&r=" + (+new Date());,您可能不会看到 url(因为它是扩展名或本地内容,因此浏览器不会向您显示)并且没有行号。
2021-03-17 00:48:50
顺便说一句,您应该使用服务器而不是 JS 获取时间戳(甚至可能只是获取版本,而不是时间戳)。
2021-03-31 00:48:50
事实上,JS 应该只发送原始数据,而 PHP 应该注意忽略加载错误等。
2021-04-06 00:48:50
我在 JS 端做了一些处理,因为我只想报告第一个相关错误,所以我在真正的错误出现后将 onerror 函数重新分配为空。这也可以防止循环中发生的错误 ddos​​'ing 我的服务器.
2021-04-08 00:48:50
该 URL 均匀分布在我网站的页面中。考虑到它是 FF 和 chrome,我猜也是书签,甚至扩展或主题。但是,我希望能够在安全地忽略它之前准确地重现此错误消息。
2021-04-09 00:48:50

我有一个类似的问题:我的脚本由一个子域提供服务,并且属于同一来源限制。但是,我通过以下方式解决了这个问题:

1)像这样添加每个脚本标签:

<script type="text/javascript" src="http://subdomain.mydomain.tld" crossorigin="*.mydomain.tld" />

2)通过在每个虚拟主机中添加以下内容来修改apache httpd.conf(您必须启用mod_headers):

<IfModule mod_headers.c>
Header add Access-Control-Allow-Origin "*.mydomain.tld"
</IfModule>

希望这可以帮助 ...

编辑

在我的一台服务器上,除了更换

*.mydomain.tld

经过

*

请注意可能允许 * 钓鱼扩展信息的缺陷。有关 CORS、同源、img 和字体、cdn 的文档可用,但有关脚本标记跨域详细信息的可用文档很少。

“*.mydomain.tld”不是跨域属性developer.mozilla.org/en-US/docs/Web/HTML/...
2021-03-14 00:48:50