对各种异步回调都使用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里边

浙公网安备 33010602011771号