对各种异步回调都使用try catch错误上报
var moon_init = function () { // 前端的@cunjinli (function () { // @cunjinli 重写alert函数, moonsafe监控 var _alert = window.alert; window.__alertList = []; window.alert = function (msg) { _alert(msg); window.__alertList.push(msg); }; })(); /** * moonsafe @cunjinli 加在这里 */ (function () { // if (window.__nonce_str) { // var __old_createElement = document.createElement; // document.createElement = function(tagName) { // var node = __old_createElement.apply(this, arguments); // if (typeof tagName == 'object') { // tagName = tagName.toString(); // } // if (typeof tagName == 'string' && tagName.toLowerCase() == 'script') { // node.setAttribute("nonce", window.__nonce_str); // } // return node; // } // } if (window.addEventListener && window.__DEBUGINFO && Math.random() < 0.01) { window.addEventListener("load", function () { var node = document.createElement('script'); node.src = __DEBUGINFO.safe_js; node.type = 'text/javascript'; node.async = true; var head = document.head || (document.getElementsByTagName("head")[0]); head.appendChild(node); }); } })(); /** * mooncatch * 对各种异步回调都使用try catch错误上报 * @radeonwu raphealguo */ (function () { var inWx = (/MicroMessenger/i).test(navigator.userAgent); var inMp = (/MPAPP/i).test(navigator.userAgent); var _idkey = 121261; //上报的idkey 添加默认上报值 var _startKey; //开始的key var _limit; //上报的key的长度 var _badjsId; var _reportOpt; //上报的额外信息 var _extInfo; //附加的预留字段,如网络采样率采样率network_rate, 总体上报率rate var MOON_LISTENER_ERROR_KEY_OFFSET = 2; //addEventListener上报时的偏移量为2 var MOON_AJAX_NETWORK_OFFSET = 4; //network错误时的上报偏移量为4,这里在ajax.js中上报,这里需要加入采样率 var MOON_ASYNC_ERROR_KEY_OFFSET = 9; //setTimeout和setInterval上报时的偏移量为9 var MOON_LOCALSTORAGE_ERROR_KEY_OFFSET = 10; //localstorage.setItem失败时的偏移量为10 window.__initCatch = function (opt) { _idkey = opt.idkey; _startKey = opt.startKey || 0; _limit = opt.limit; _badjsId = opt.badjsId; _reportOpt = opt.reportOpt || ""; _extInfo = opt.extInfo || {}; _extInfo.rate = _extInfo.rate || 0.5; } //暴露的上报函数,供core.js和ajax.js上报错误使用,array = [{offset:MOON_JSAPI_KEY_OFFSET, log:"ready", e:e}] window.__moon_report = function (array, rate_opt) { var isAcrossOrigin = false; var href = ''; try { href = top.location.href; } catch (e) { isAcrossOrigin = true; } var rate = 0.5; if (!!_extInfo && !!_extInfo.rate) { rate = _extInfo.rate; } if (!!rate_opt && (typeof rate_opt == 'number')) { rate = rate_opt; } if ( (!(/mp\.weixin\.qq\.com/).test(location.href) && !(/payapp\.weixin\.qq\.com/).test(location.href)) || Math.random() > rate || !(inWx || inMp) || (top != window && !isAcrossOrigin && !(/mp\.weixin\.qq\.com/).test(href)) ) { //return ; } if (isObject(array)) array = [array]; if (!isArray(array) || _idkey == '') return; var data = ""; var log = []; //存放array中每个对象关联的log var key = []; //存放array中每个上报的key var val = []; //存放array中每个上报的value var idkey = []; //如果这里没有opt.limit,直接上报到startKey if (typeof _limit != "number") { _limit = Infinity; } for (var i = 0; i < array.length; i++) { var item = array[i] || {}; if (item.offset > _limit) continue; //上报的偏移量超过limit if (typeof item.offset != "number") continue; if (item.offset == MOON_AJAX_NETWORK_OFFSET && !!_extInfo && !!_extInfo.network_rate && Math.random() >= _extInfo.network_rate) { continue; } //log[i] = item.log || ""; var k = _limit == Infinity ? _startKey : (_startKey + item.offset); log[i] = (("[moon]" + _idkey + "_" + k + ";") + item.log + ";" + getErrorMessage(item.e || {})) || ""; key[i] = k; val[i] = 1; } for (var j = 0; j < key.length; j++) { idkey[j] = _idkey + "_" + key[j] + "_" + val[j]; data = data + "&log" + j + "=" + log[j]; } if (idkey.length > 0) { // sendReport("idkey=" + idkey.join(";") + "&lc=" + log.length + data); sendReport("POST", location.protocol + '//mp.weixin.qq.com/mp/jsmonitor?', "idkey=" + idkey.join(";") + "&r=" + Math.random() + "&lc=" + log.length + data); // 把图文消息的错误上报一份到badjs,只支持get请求 // 这里由于量比较大,把badjs的内层怼爆了,这里加多一个采样,并且去掉用户的信息 var rate = 1; if (_extInfo && _extInfo.badjs_rate) { // 初始化时的badjs采样率 rate = _extInfo.badjs_rate; } if (Math.random() < rate) { data = data.replace(/uin\:(.)*\|biz\:(.)*\|mid\:(.)*\|idx\:(.)*\|sn\:(.)*\|/, ''); if (!!_badjsId) { var _img = new Image(); var _src = 'https://badjs.weixinbridge.com/badjs?id=' + _badjsId + '&level=4&from=' + encodeURIComponent(location.host) + '&msg=' + encodeURIComponent(data); _img.src = _src.slice(0, 1024); } // badjs同时报一份到新监控 if (typeof WX_BJ_REPORT != "undefined" && WX_BJ_REPORT.BadJs) { for (var i = 0; i < array.length; i++) { var item = array[i] || {}; if (item.e) { WX_BJ_REPORT.BadJs.onError(item.e, { _info: item.log }); } else { var name = /[^:;]*/.exec(item.log)[0]; WX_BJ_REPORT.BadJs.report(name, item.log, { mid: "mmbizwap:Monitor" }); } } } } else { //虽然采样没有执行 但实际是有被BadJs.onError,置位一下 for (var i = 0; i < array.length; i++) { var item = array[i] || {}; if (item.e) { item.e.BADJS_EXCUTED = true; } } } } } function isArray(obj) { //判断输入是否为数组 return Object.prototype.toString.call(obj) === '[object Array]'; } function isObject(obj) { //判断输入是否为对象 return Object.prototype.toString.call(obj) === '[object Object]'; } function getErrorMessage(e) { var stack = e.stack + ' ' + e.toString() || ""; //错误堆栈信息 try { //先取出res域名 if (!window.testenv_reshost) { stack = stack.replace(/http(s)?:\/\/res\.wx\.qq\.com/g, ""); } else { var host = 'http(s)?://' + window.testenv_reshost; var reg = new RegExp(host, 'g'); stack = stack.replace(reg, ""); } //提取最后一个.js前边的 var reg = /\/([^.]+)\/js\/(\S+?)\.js(\,|:)?/g; while (reg.test(stack)) { // stack = stack.replace(reg, "3"); 解决$问题 stack = stack.replace(reg, function (a, b, c, d, e, f) { return c + d }); } } catch (e) { stack = e.stack ? e.stack : "" //错误堆栈信息 } var ret = []; for (o in _reportOpt) { if (_reportOpt.hasOwnProperty(o)) { ret.push(o + ":" + _reportOpt[o]); } } ret.push("STK:" + stack.replace(/\n/g, "")); return ret.join("|"); } function sendReport(type, url, data) { //post方法用于提交数据 if (!/^mp\.weixin\.qq\.com$/.test(location.hostname)) { //非MP域名使用 img方式上报 var tmp = []; data = data.replace(location.href, (location.origin || "") + (location.pathname || "")).replace("#wechat_redirect", "").replace("#rd", "").split("&"); for (var i = 0, il = data.length; i < il; i++) { var a = data[i].split("="); if (!!a[0] && !!a[1]) { tmp.push(a[0] + "=" + encodeURIComponent(a[1])); } } var _img = new window.Image(); _img.src = (url + tmp.join("&")).substr(0, 1024); return; } var xmlobj; //定义XMLHttpRequest对象 if (window.ActiveXObject) { //如果当前浏览器支持Active Xobject,则创建ActiveXObject对象 try { xmlobj = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlobj = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { xmlobj = false; } } } else if (window.XMLHttpRequest) { //如果当前浏览器支持XMLHttpRequest,则创建XMLHttpRequest对象 xmlobj = new XMLHttpRequest(); } if (!xmlobj) return; //xmlobj.open("POST", location.protocol + "//mp.weixin.qq.com/mp/jsmonitor?", true); xmlobj.open(type, url, true); xmlobj.setRequestHeader("cache-control", "no-cache"); xmlobj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); //设置请求头信息 xmlobj.setRequestHeader("X-Requested-With", "XMLHttpRequest"); xmlobj.send(data); //发送数据 } function catTimeout(foo) { return function (cb, timeout) { if (typeof cb === 'string') { try { cb = new Function(cb); } catch (err) { throw err; } } var args = [].slice.call(arguments, 2); var _cb = cb; cb = function () { try { return _cb.apply(this, (args.length && args) || arguments); } catch (error) { if (error.stack && console && console.error) { //chrome有bug,特定情况下看不到throw的error,这里console.error下,防止给调试留坑 console.error("[TryCatch]" + error.stack); } if (!!_idkey && !!window.__moon_report) { //没有初始化_key,直接throw error //sendReport(error); window.__moon_report([{ offset: MOON_ASYNC_ERROR_KEY_OFFSET, log: "timeout_error;host:" + location.host, e: error }]); //breakOnError(timeoutkey); } throw error; } } return foo(cb, timeout); }; }; window.setTimeout = catTimeout(window.setTimeout); window.setInterval = catTimeout(window.setInterval); if (Math.random() < 0.01 && !!window.Document && !!window.HTMLElement) { var cb_map = {}; var moon_lid = 0; function catAddListener(foo) { return function (type, cb, useCapture) { if (typeof useCapture === "undefined") { var useCapture = false; } var that = this; var _cb = cb || function () { }; cb = function () { try { //arguments[0].currentTarget.setAttribute("data-moon_lid") = moon_lid; //_cb.moon_lid = moon_lid; return _cb.apply(that, arguments); } catch (error) { if (error.stack && console && console.error) { //chrome有bug,特定情况下看不到throw的error,这里console.error下,防止给调试留坑 console.error("[TryCatch]" + error.stack); } if (!!_idkey && !!window.__moon_report) { //没有初始化_key,直接throw error window.__moon_report([{ offset: MOON_LISTENER_ERROR_KEY_OFFSET, log: "listener_error;type:" + type + ";host:" + location.host, e: error }]); //breakOnError(timeoutkey); } throw error; } } _cb.moon_lid = moon_lid; cb_map[moon_lid] = cb; moon_lid++; return foo.call(that, type, cb, useCapture); } } function catRemoveListener(foo) { return function (type, cb, useCapture) { if (typeof useCapture === "undefined") { var useCapture = false; } var that = this; cb = cb_map[cb.moon_lid]; return foo.call(that, type, cb, useCapture); } } Document.prototype.addEventListener = catAddListener(Document.prototype.addEventListener); Document.prototype.removeEventListener = catRemoveListener(Document.prototype.removeEventListener); HTMLElement.prototype.addEventListener = catAddListener(HTMLElement.prototype.addEventListener); HTMLElement.prototype.removeEventListener = catRemoveListener(HTMLElement.prototype.removeEventListener); } //alert("setItem begin"); //window.localStorage.setItem = function(){a=c;}//故意 var ua = window.navigator.userAgent; if ((/ip(hone|ad|od)/i.test(ua) || /android/i.test(ua)) && !/windows phone/i.test(ua) && !!window.localStorage && !!window.localStorage.setItem) { var _setItem = window.localStorage.setItem; var count = 0; window.localStorage.setItem = function (k, v) { if (count >= 10) { //一直失败 不要再继续试了,可能类似safari无痕模式 不允许写入了 return; } try { _setItem.call(window.localStorage, k, v); } catch (error) { //alert(error); if (error.stack && console && console.error) { //chrome有bug,特定情况下看不到throw的error,这里console.error下,防止给调试留坑 console.error("[TryCatch]" + error.stack); } window.__moon_report([{ offset: MOON_LOCALSTORAGE_ERROR_KEY_OFFSET, log: "localstorage_error;" + error.toString(), e: error }]); count++; if (count >= 3 && !!window.moon && window.moon.clear) { // 可能爆满 清理一下localstorage moon.clear(); } } } //alert("setItem end"); } })(); // 后面的@cunjinli }; moon_init(); //由于moon异步化,所以有些逻辑需要moon加载完之后才执行的 放到全局callback函数__moon_initcallback里边
view-source:https://mp.weixin.qq.com/s/_xsb_91-eQAq10IyDa2tvQ
var moon_init = function () {
// 前端的@cunjinli
(function () {
// @cunjinli 重写alert函数, moonsafe监控
var _alert = window.alert;
window.__alertList = [];
window.alert = function (msg) {
_alert(msg);
window.__alertList.push(msg);
};
})();
/**
* moonsafe @cunjinli 加在这里
*/
(function () {
// if (window.__nonce_str) {
// var __old_createElement = document.createElement;
// document.createElement = function(tagName) {
// var node = __old_createElement.apply(this, arguments);
// if (typeof tagName == 'object') {
// tagName = tagName.toString();
// }
// if (typeof tagName == 'string' && tagName.toLowerCase() == 'script') {
// node.setAttribute("nonce", window.__nonce_str);
// }
// return node;
// }
// }
if (window.addEventListener && window.__DEBUGINFO && Math.random() < 0.01) {
window.addEventListener("load", function () {
var node = document.createElement('script');
node.src = __DEBUGINFO.safe_js;
node.type = 'text/javascript';
node.async = true;
var head = document.head || (document.getElementsByTagName("head")[0]);
head.appendChild(node);
});
}
})();
/**
* mooncatch
* 对各种异步回调都使用try catch错误上报
* @radeonwu raphealguo
*/
(function () {
var inWx = (/MicroMessenger/i).test(navigator.userAgent);
var inMp = (/MPAPP/i).test(navigator.userAgent);
var _idkey = 121261; //上报的idkey 添加默认上报值
var _startKey; //开始的key
var _limit; //上报的key的长度
var _badjsId;
var _reportOpt; //上报的额外信息
var _extInfo; //附加的预留字段,如网络采样率采样率network_rate, 总体上报率rate
var MOON_LISTENER_ERROR_KEY_OFFSET = 2; //addEventListener上报时的偏移量为2
var MOON_AJAX_NETWORK_OFFSET = 4; //network错误时的上报偏移量为4,这里在ajax.js中上报,这里需要加入采样率
var MOON_ASYNC_ERROR_KEY_OFFSET = 9; //setTimeout和setInterval上报时的偏移量为9
var MOON_LOCALSTORAGE_ERROR_KEY_OFFSET = 10; //localstorage.setItem失败时的偏移量为10
window.__initCatch = function (opt) {
_idkey = opt.idkey;
_startKey = opt.startKey || 0;
_limit = opt.limit;
_badjsId = opt.badjsId;
_reportOpt = opt.reportOpt || "";
_extInfo = opt.extInfo || {};
_extInfo.rate = _extInfo.rate || 0.5;
}
//暴露的上报函数,供core.js和ajax.js上报错误使用,array = [{offset:MOON_JSAPI_KEY_OFFSET, log:"ready", e:e}]
window.__moon_report = function (array, rate_opt) {
var isAcrossOrigin = false;
var href = '';
try {
href = top.location.href;
} catch (e) {
isAcrossOrigin = true;
}
var rate = 0.5;
if (!!_extInfo && !!_extInfo.rate) {
rate = _extInfo.rate;
}
if (!!rate_opt && (typeof rate_opt == 'number')) {
rate = rate_opt;
}
if (
(!(/mp\.weixin\.qq\.com/).test(location.href) && !(/payapp\.weixin\.qq\.com/).test(location.href)) ||
Math.random() > rate ||
!(inWx || inMp) ||
(top != window && !isAcrossOrigin && !(/mp\.weixin\.qq\.com/).test(href))
) {
//return ;
}
if (isObject(array))
array = [array];
if (!isArray(array) || _idkey == '')
return;
var data = "";
var log = []; //存放array中每个对象关联的log
var key = []; //存放array中每个上报的key
var val = []; //存放array中每个上报的value
var idkey = [];
//如果这里没有opt.limit,直接上报到startKey
if (typeof _limit != "number") {
_limit = Infinity;
}
for (var i = 0; i < array.length; i++) {
var item = array[i] || {};
if (item.offset > _limit) continue; //上报的偏移量超过limit
if (typeof item.offset != "number") continue;
if (item.offset == MOON_AJAX_NETWORK_OFFSET && !!_extInfo && !!_extInfo.network_rate && Math.random() >= _extInfo.network_rate) {
continue;
}
//log[i] = item.log || "";
var k = _limit == Infinity ? _startKey : (_startKey + item.offset);
log[i] = (("[moon]" + _idkey + "_" + k + ";") + item.log + ";" + getErrorMessage(item.e || {})) || "";
key[i] = k;
val[i] = 1;
}
for (var j = 0; j < key.length; j++) {
idkey[j] = _idkey + "_" + key[j] + "_" + val[j];
data = data + "&log" + j + "=" + log[j];
}
if (idkey.length > 0) {
// sendReport("idkey=" + idkey.join(";") + "&lc=" + log.length + data);
sendReport("POST", location.protocol + '//mp.weixin.qq.com/mp/jsmonitor?', "idkey=" + idkey.join(";") + "&r=" + Math.random() + "&lc=" + log.length + data);
// 把图文消息的错误上报一份到badjs,只支持get请求
// 这里由于量比较大,把badjs的内层怼爆了,这里加多一个采样,并且去掉用户的信息
var rate = 1;
if (_extInfo && _extInfo.badjs_rate) { // 初始化时的badjs采样率
rate = _extInfo.badjs_rate;
}
if (Math.random() < rate) {
data = data.replace(/uin\:(.)*\|biz\:(.)*\|mid\:(.)*\|idx\:(.)*\|sn\:(.)*\|/, '');
if (!!_badjsId) {
var _img = new Image();
var _src = 'https://badjs.weixinbridge.com/badjs?id=' + _badjsId + '&level=4&from=' + encodeURIComponent(location.host) + '&msg=' + encodeURIComponent(data);
_img.src = _src.slice(0, 1024);
}
// badjs同时报一份到新监控
if (typeof WX_BJ_REPORT != "undefined" && WX_BJ_REPORT.BadJs) {
for (var i = 0; i < array.length; i++) {
var item = array[i] || {};
if (item.e) {
WX_BJ_REPORT.BadJs.onError(item.e, { _info: item.log });
} else {
var name = /[^:;]*/.exec(item.log)[0];
WX_BJ_REPORT.BadJs.report(name, item.log, { mid: "mmbizwap:Monitor" });
}
}
}
} else {
//虽然采样没有执行 但实际是有被BadJs.onError,置位一下
for (var i = 0; i < array.length; i++) {
var item = array[i] || {};
if (item.e) {
item.e.BADJS_EXCUTED = true;
}
}
}
}
}
function isArray(obj) { //判断输入是否为数组
return Object.prototype.toString.call(obj) === '[object Array]';
}
function isObject(obj) { //判断输入是否为对象
return Object.prototype.toString.call(obj) === '[object Object]';
}
function getErrorMessage(e) {
var stack = e.stack + ' ' + e.toString() || ""; //错误堆栈信息
try {
//先取出res域名
if (!window.testenv_reshost) {
stack = stack.replace(/http(s)?:\/\/res\.wx\.qq\.com/g, "");
} else {
var host = 'http(s)?://' + window.testenv_reshost;
var reg = new RegExp(host, 'g');
stack = stack.replace(reg, "");
}
//提取最后一个.js前边的
var reg = /\/([^.]+)\/js\/(\S+?)\.js(\,|:)?/g;
while (reg.test(stack)) {
// stack = stack.replace(reg, "3"); 解决$问题
stack = stack.replace(reg, function (a, b, c, d, e, f) {
return c + d
});
}
} catch (e) {
stack = e.stack ? e.stack : "" //错误堆栈信息
}
var ret = [];
for (o in _reportOpt) {
if (_reportOpt.hasOwnProperty(o)) {
ret.push(o + ":" + _reportOpt[o]);
}
}
ret.push("STK:" + stack.replace(/\n/g, ""));
return ret.join("|");
}
function sendReport(type, url, data) { //post方法用于提交数据
if (!/^mp\.weixin\.qq\.com$/.test(location.hostname)) { //非MP域名使用 img方式上报
var tmp = [];
data = data.replace(location.href, (location.origin || "") + (location.pathname || "")).replace("#wechat_redirect", "").replace("#rd", "").split("&");
for (var i = 0, il = data.length; i < il; i++) {
var a = data[i].split("=");
if (!!a[0] && !!a[1]) {
tmp.push(a[0] + "=" + encodeURIComponent(a[1]));
}
}
var _img = new window.Image();
_img.src = (url + tmp.join("&")).substr(0, 1024);
return;
}
var xmlobj; //定义XMLHttpRequest对象
if (window.ActiveXObject) { //如果当前浏览器支持Active Xobject,则创建ActiveXObject对象
try {
xmlobj = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlobj = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlobj = false;
}
}
} else if (window.XMLHttpRequest) { //如果当前浏览器支持XMLHttpRequest,则创建XMLHttpRequest对象
xmlobj = new XMLHttpRequest();
}
if (!xmlobj) return;
//xmlobj.open("POST", location.protocol + "//mp.weixin.qq.com/mp/jsmonitor?", true);
xmlobj.open(type, url, true);
xmlobj.setRequestHeader("cache-control", "no-cache");
xmlobj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); //设置请求头信息
xmlobj.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xmlobj.send(data); //发送数据
}
function catTimeout(foo) {
return function (cb, timeout) {
if (typeof cb === 'string') {
try {
cb = new Function(cb);
} catch (err) {
throw err;
}
}
var args = [].slice.call(arguments, 2);
var _cb = cb;
cb = function () {
try {
return _cb.apply(this, (args.length && args) || arguments);
} catch (error) {
if (error.stack && console && console.error) { //chrome有bug,特定情况下看不到throw的error,这里console.error下,防止给调试留坑
console.error("[TryCatch]" + error.stack);
}
if (!!_idkey && !!window.__moon_report) { //没有初始化_key,直接throw error
//sendReport(error);
window.__moon_report([{ offset: MOON_ASYNC_ERROR_KEY_OFFSET, log: "timeout_error;host:" + location.host, e: error }]);
//breakOnError(timeoutkey);
}
throw error;
}
}
return foo(cb, timeout);
};
};
window.setTimeout = catTimeout(window.setTimeout);
window.setInterval = catTimeout(window.setInterval);
if (Math.random() < 0.01 && !!window.Document && !!window.HTMLElement) {
var cb_map = {};
var moon_lid = 0;
function catAddListener(foo) {
return function (type, cb, useCapture) {
if (typeof useCapture === "undefined") {
var useCapture = false;
}
var that = this;
var _cb = cb || function () { };
cb = function () {
try {
//arguments[0].currentTarget.setAttribute("data-moon_lid") = moon_lid;
//_cb.moon_lid = moon_lid;
return _cb.apply(that, arguments);
} catch (error) {
if (error.stack && console && console.error) { //chrome有bug,特定情况下看不到throw的error,这里console.error下,防止给调试留坑
console.error("[TryCatch]" + error.stack);
}
if (!!_idkey && !!window.__moon_report) { //没有初始化_key,直接throw error
window.__moon_report([{ offset: MOON_LISTENER_ERROR_KEY_OFFSET, log: "listener_error;type:" + type + ";host:" + location.host, e: error }]);
//breakOnError(timeoutkey);
}
throw error;
}
}
_cb.moon_lid = moon_lid;
cb_map[moon_lid] = cb;
moon_lid++;
return foo.call(that, type, cb, useCapture);
}
}
function catRemoveListener(foo) {
return function (type, cb, useCapture) {
if (typeof useCapture === "undefined") {
var useCapture = false;
}
var that = this;
cb = cb_map[cb.moon_lid];
return foo.call(that, type, cb, useCapture);
}
}
Document.prototype.addEventListener = catAddListener(Document.prototype.addEventListener);
Document.prototype.removeEventListener = catRemoveListener(Document.prototype.removeEventListener);
HTMLElement.prototype.addEventListener = catAddListener(HTMLElement.prototype.addEventListener);
HTMLElement.prototype.removeEventListener = catRemoveListener(HTMLElement.prototype.removeEventListener);
}
//alert("setItem begin");
//window.localStorage.setItem = function(){a=c;}//故意
var ua = window.navigator.userAgent;
if ((/ip(hone|ad|od)/i.test(ua) || /android/i.test(ua)) && !/windows phone/i.test(ua) && !!window.localStorage && !!window.localStorage.setItem) {
var _setItem = window.localStorage.setItem;
var count = 0;
window.localStorage.setItem = function (k, v) {
if (count >= 10) { //一直失败 不要再继续试了,可能类似safari无痕模式 不允许写入了
return;
}
try {
_setItem.call(window.localStorage, k, v);
} catch (error) {
//alert(error);
if (error.stack && console && console.error) { //chrome有bug,特定情况下看不到throw的error,这里console.error下,防止给调试留坑
console.error("[TryCatch]" + error.stack);
}
window.__moon_report([{ offset: MOON_LOCALSTORAGE_ERROR_KEY_OFFSET, log: "localstorage_error;" + error.toString(), e: error }]);
count++;
if (count >= 3 && !!window.moon && window.moon.clear) {
// 可能爆满 清理一下localstorage
moon.clear();
}
}
}
//alert("setItem end");
}
})();
// 后面的@cunjinli
};
moon_init();
//由于moon异步化,所以有些逻辑需要moon加载完之后才执行的 放到全局callback函数__moon_initcallback里边