对各种异步回调都使用try catch错误上报

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
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 @   papering  阅读(235)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2021-06-08 在结构体嵌入接口
2021-06-08 排序 /src/sort/zfuncversion.go:136
2021-06-08 Modification should be made to copies of the returned MD.
2021-06-08 setTimeout 定时器的编号 实际延时比设定值更久的原因:最小延迟时间
2020-06-08 Crypto.getRandomValues()
2020-06-08 Profile Guided Optimization Link Time Optimization
2019-06-08 tmp
点击右上角即可分享
微信分享提示