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

 

 

 

posted @ 2022-06-08 14:03  papering  阅读(208)  评论(0编辑  收藏  举报