cri*_*ris 26 javascript error-handling google-tag-manager
最近,我得到这个postMessage无法克隆错误.它发生在大多数最新的浏览器上,如Chrome 68,Firefox 61.0,IE11,Edge.
无法在'Window'上执行'postMessage':
function (a){if(qe.$a.hasOwnProperty(a))return qe.$a[a]}无法克隆.
堆栈跟踪是:
错误:无法在'Window'上执行'postMessage':
function (a){if(qe.$a.hasOwnProperty(a))return qe.$a[a]}无法克隆.
在_reportEvent(eval at(:1:35637),:94:35)
at eval(eval at(:1:35637),:55:5)
at eval(eval at(:1:35637),:433:11 )
在DevTools中搜索我的页面gtm.js源代码显示为代码片段的来源:
我的网页上有Google跟踪代码管理器跟踪代码.为什么会这样?
Bha*_*ata 14
如果结构化克隆算法无法复制某些内容,则会一直发生这种情况.该算法用于window.postMessage.如果我们从window.postMessage第一个参数中读取文档:
message
要发送到另一个窗口的数据.使用结构化克隆算法序列化数据.
然后从结构化克隆算法中打开描述(参见上面的上一个链接),然后我们可以阅读:
结构化克隆算法是由HTML5规范定义的用于复制复杂JavaScript对象的算法.在通过
postMessage()或存储对象时,在与工作人员之间传输数据时使用它IndexedDB.它通过递归输入对象来构建克隆,同时保持先前访问过的引用的映射,以避免无限遍历循环.不适用于结构化克隆的东西
ErrorFunction结构化克隆算法不能复制和对象; 试图这样做将引发DATA_CLONE_ERR异常.- 尝试克隆
DOM节点同样会引发DATA_CLONE_ERR异常.不保留对象的某些参数:
- 不保留对象的
lastIndex字段RegExp.- 属性描述符,setter和getter(以及类似的类似元数据的特性)不会重复.例如,如果使用属性描述符将对象标记为只读,则它将以重复方式进行读写,因为这是默认条件.
- 原型链不会走路和重复.
支持的类型
我用一些对象测试了它,当发生这种情况时我会向你展示以下示例...
自定义函数示例
var obj = {something: function(){}};
window.postMessage(obj, '*'); // DataCloneErrorRun Code Online (Sandbox Code Playgroud)
原生函数示例
var obj = {something: window.alert};
window.postMessage(obj, '*'); // DataCloneErrorRun Code Online (Sandbox Code Playgroud)
同样的,我们将用相同的原生功能看Boolean,Date,String,RegExp,Number,Array.
本机对象的示例
var obj = {something: document};
window.postMessage(obj, '*'); // DataCloneErrorRun Code Online (Sandbox Code Playgroud)
HTML元素对象的示例
var obj = {something: document.createElement('b')};
window.postMessage(obj, '*'); // DataCloneErrorRun Code Online (Sandbox Code Playgroud)
如果我们从上面的结构化克隆算法中读取描述,我们可以编写更多示例,但我认为这就足够了.
在我们的代码中,我们只能使用对象中支持的类型(请参阅上面的列表).但是在我们的代码中,我们不得不从这段代码中联系开发人员,并写下他们如何纠正他们的代码.在Google跟踪代码管理器的情况下,您可以将其写入官方Google跟踪代码管理器论坛,并说明他们如何更正代码.
某些浏览器的解决方法
在某些浏览器中,出于安全原因,您无法覆盖本机方法.例如,IE不允许覆盖window.postMessage.但是像Chrome这样的其他浏览器允许覆盖此方法,如下所示:
var postMessageTemp = window.postMessage;
window.postMessage = function(message, targetOrigin, transfer)
{
postMessageTemp(JSON.parse(JSON.stringify(message)), targetOrigin, transfer)
};
Run Code Online (Sandbox Code Playgroud)
但请注意,这window是JavaScript上下文的全局对象,它不是从...创建的prototype.换句话说:你不能用它来覆盖它window.prototype.postMessage = ....
解决方法示例
var obj = {something: window};
var postMessageTemp = window.postMessage;
window.postMessage = function(message, targetOrigin, transfer)
{
function cloneObject(obj)
{
var clone = {};
for(var i in obj)
{
if(typeof(obj[i]) == 'object' && obj[i] != null)
{
if((''+obj[i]) == '[object Window]')
{
delete obj[i];
continue;
}
clone[i] = cloneObject(obj[i]);
}
else
clone[i] = obj[i];
}
return clone;
}
// to avoid weird error causing by window object by JSON.stringify() execution.
var clone = cloneObject(message);
postMessageTemp(JSON.parse(JSON.stringify(clone)), targetOrigin, transfer)
};
window.postMessage(obj, '*');
console.log('We do not have any errors.');Run Code Online (Sandbox Code Playgroud)
如何实现此变通方法
请window.postMessage在Google跟踪代码管理器脚本之前将此覆盖功能放在HTML页面的脚本部分中.但是,您可以通过更好的方式帮助Google跟踪代码管理器中的开发人员了解并纠正此错误,您可以等待更正的Google跟踪代码管理器脚本.
这些错误是由Facebook抓取工具执行JavaScript代码引起的.
我从这些IP(所有Facebook IP范围内)和用户代理中发生了此错误:
66.220.149.14 - Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0
31.13.115.2 - Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
173.252.87.1 - Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
69.171.251.11 - facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)
Run Code Online (Sandbox Code Playgroud)
要获取Facebook爬虫IP的最新列表,请参阅https://developers.facebook.com/docs/sharing/webmasters/crawler/中的以下命令:
whois -h whois.radb.net -- '-i origin AS32934' | grep ^route
您需要更新错误报告机制以过滤掉这些IP范围中的错误.
您可以通过在发生错误时确定用户的IP地址,在JavaScript的客户端执行此操作(请参阅如何使用JavaScript获取客户端的IP地址?).
或者您可以在服务器端执行此操作.以下是ASP.NET MVC的示例:
using System.Linq;
// Requires the IPAddressRange NuGet library:
// https://www.nuget.org/packages/IPAddressRange/
using NetTools;
public class FacebookClientDetector
{
/// <summary>
/// The list of CIDR ranges of facebook IPs that its crawlers use.
/// To generate, run
/// whois -h whois.radb.net -- '-i origin AS32934' | grep ^route
/// https://developers.facebook.com/docs/sharing/webmasters/crawler/
/// </summary>
static readonly string[] facebookIpRanges = new string[] {
"204.15.20.0/22",
"69.63.176.0/20",
"66.220.144.0/20",
"66.220.144.0/21",
"69.63.184.0/21",
"69.63.176.0/21",
"74.119.76.0/22",
"69.171.255.0/24",
"173.252.64.0/18",
"69.171.224.0/19",
"69.171.224.0/20",
"103.4.96.0/22",
"69.63.176.0/24",
"173.252.64.0/19",
"173.252.70.0/24",
"31.13.64.0/18",
"31.13.24.0/21",
"66.220.152.0/21",
"66.220.159.0/24",
"69.171.239.0/24",
"69.171.240.0/20",
"31.13.64.0/19",
"31.13.64.0/24",
"31.13.65.0/24",
"31.13.67.0/24",
"31.13.68.0/24",
"31.13.69.0/24",
"31.13.70.0/24",
"31.13.71.0/24",
"31.13.72.0/24",
"31.13.73.0/24",
"31.13.74.0/24",
"31.13.75.0/24",
"31.13.76.0/24",
"31.13.77.0/24",
"31.13.96.0/19",
"31.13.66.0/24",
"173.252.96.0/19",
"69.63.178.0/24",
"31.13.78.0/24",
"31.13.79.0/24",
"31.13.80.0/24",
"31.13.82.0/24",
"31.13.83.0/24",
"31.13.84.0/24",
"31.13.85.0/24",
"31.13.86.0/24",
"31.13.87.0/24",
"31.13.88.0/24",
"31.13.89.0/24",
"31.13.90.0/24",
"31.13.91.0/24",
"31.13.92.0/24",
"31.13.93.0/24",
"31.13.94.0/24",
"31.13.95.0/24",
"69.171.253.0/24",
"69.63.186.0/24",
"31.13.81.0/24",
"179.60.192.0/22",
"179.60.192.0/24",
"179.60.193.0/24",
"179.60.194.0/24",
"179.60.195.0/24",
"185.60.216.0/22",
"45.64.40.0/22",
"185.60.216.0/24",
"185.60.217.0/24",
"185.60.218.0/24",
"185.60.219.0/24",
"129.134.0.0/16",
"157.240.0.0/16",
"157.240.8.0/24",
"157.240.0.0/24",
"157.240.1.0/24",
"157.240.2.0/24",
"157.240.3.0/24",
"157.240.4.0/24",
"157.240.5.0/24",
"157.240.6.0/24",
"157.240.7.0/24",
"157.240.9.0/24",
"157.240.10.0/24",
"157.240.16.0/24",
"157.240.19.0/24",
"157.240.11.0/24",
"157.240.12.0/24",
"157.240.13.0/24",
"157.240.14.0/24",
"157.240.15.0/24",
"157.240.17.0/24",
"157.240.18.0/24",
"157.240.20.0/24",
"157.240.21.0/24",
"157.240.22.0/24",
"157.240.23.0/24",
"129.134.0.0/17",
"157.240.0.0/17",
"69.171.250.0/24",
"204.15.20.0/22",
"69.63.176.0/20",
"69.63.176.0/21",
"69.63.184.0/21",
"66.220.144.0/20",
"69.63.176.0/20",
};
public static bool IsFacebookClient(string ip)
{
IPAddressRange parsedIp;
if (!IPAddressRange.TryParse(ip, out parsedIp)) {
return false;
}
return facebookIpRanges.Any(cidr => IPAddressRange.Parse(cidr).Contains(parsedIp));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4915 次 |
| 最近记录: |