Last active
May 18, 2023 01:00
-
-
Save mqudsi/2f570cf58d7d293ba27217a308659dfe to your computer and use it in GitHub Desktop.
Client-side JavaScript error reporting library, compatible with ancient browsers.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// JavaScript error reporting library. | |
// Copyright (c) Mahmoud Al-Qudsi, NeoSmart Technologies. All rights reserved. | |
// Licensed under the MIT License. This copyright notice should be preserved. | |
function addScript(url) { | |
document.write("<script type='text/javascript' src='" + url + "'><\/script>"); | |
} | |
if (typeof (JSON) === "undefined") { | |
addScript("/EasyRE/lib/polyfill/json3/json3.min.js"); | |
} | |
function getStack() { | |
var stack = ""; | |
for (var func = arguments.callee.caller, i = 0; | |
func && func.arguments !== undefined && i <= 10; | |
++i, func = func.caller) | |
{ | |
var args = "("; | |
for (var a = 0; a < func.arguments.length; ++a) { | |
if (typeof (func.arguments[a]) === "string") { | |
args += '`' + func.arguments[a] + '`'; | |
} else { | |
args += func.arguments[a].toString(); | |
} | |
if (a != func.arguments.length - 1) { | |
args += ", "; | |
} | |
} | |
args += ")"; | |
if (func.name !== undefined && func.name.length > 0) { | |
stack += ("* " + func.name + args); | |
} else if (func.$name !== undefined && func.$name.length > 0) { | |
stack += ("* " + func.$name + args); | |
} else { | |
var matches = func.toString().match(/function\s*([^(\s]*)/) | |
if (matches != null && matches.length > 0) { | |
if (matches[1].length > 0) { | |
stack += ("* " + matches[1] + args); | |
} else { | |
stack += ("* anonymous" + args); | |
} | |
} else { | |
stack += ("* unknown function" + args); | |
} | |
} | |
stack += "\n"; | |
} | |
return stack; | |
} | |
function reportError(error, callback) { | |
// Wrap everything in a try block to prevent recursive invocation in case of any errors here. | |
try { | |
if (typeof (callback) !== "function" || callback == null) { | |
callback = window.loadNoJs ? loadNoJs : function () { }; | |
} | |
if (Object.defineProperty === undefined) { | |
// This browser is too old, and without Object.defineProperty our script will fail to load entirely, | |
// meaning the client will fall back to HTML-only mode. | |
callback(); | |
return; | |
} | |
if (error.colno !== undefined && error.error !== undefined) { | |
// This is an ErrorEvent, not an Error | |
error = error.error; | |
} | |
if (typeof (error) === "undefined") { | |
error = { | |
filename: "", | |
line: 0, | |
colno: 0, | |
message: "undefined", | |
stack: "" | |
}; | |
} else if (typeof (error) !== "object") { | |
error = { | |
filename: "", | |
line: 0, | |
colno: 0, | |
message: error.toString(), | |
stack: "" | |
} | |
} else if (error.error !== undefined) { | |
// We do have an error object, but browser does not support error.stack | |
error.stack = getStack(); | |
} else if (error.error === undefined | |
&& ((error.srcElement !== undefined && error.srcElement !== window) | |
// Firefox 24 does not have srcElement but has explicitOriginalTarget/originalTarget/target | |
|| (error.explicitOriginalTarget && error.explicitOriginalTarget != window))) { | |
// error.error isn't defined, so this is probably an intercepted element error | |
var element = error.srcElement || error.target; | |
if (element.outerHTML && element.outerHTML.match(/bat.bing.com|googlead|googletagmanager.com|analytics.js|js.stripe.com/)) { | |
// We don't need to report these | |
return; | |
} | |
error = { | |
filename: "", | |
lineno: 0, | |
colno: 0, | |
message: "Error loading element: " + element.outerHTML, | |
stack: "" | |
}; | |
} | |
if (error.message && error.message.match(/Blocked a frame/)) { | |
// We can't do anything about this and it isn't an error | |
return; | |
} | |
// Match against the likes of moz-extension:// and chrome-extension:// | |
if (error.stack.match(/extension:\/\//)) { | |
// This error was caused by an extension on the user's PC and isn't our problem | |
return; | |
} | |
var xhr = new XMLHttpRequest(); | |
xhr.open("POST", "/EasyRE/Payment/ReportError", true); | |
xhr.setRequestHeader("RequestVerificationToken", "CfDJ8LuzKTdNvaZEjvBiklUVtA9GfPd9AqJowggwCa8dalb2eP-oajV1IfFmY6AaMcBWC3ZlyEZfiuPfiIeBx9Kt65Dc81JKAmNHliBFMYkNHDV6WYMjRGbTSBIQoDWKL2_tkZuZxHaUY89PbBcTYyoXX-DCzF7YIsnfxJbQx2UzcY3g6Y_W33jKWXpVOAxJSQ-ZVw"); | |
xhr.setRequestHeader("Content-Type", "application/json"); | |
xhr.onreadystatechange = function () { | |
if (xhr.readyState == 4 && | |
((xhr.status >= 200 && xhr.status < 300) || (xhr.status >= 400))) { | |
callback(); | |
} | |
} | |
xhr.send(JSON.stringify({ | |
"url": window.location.toString(), | |
"invoice": "329D6DFAA450F49D", | |
"error": { | |
"browser": window.navigator.userAgent, | |
"file": error.filename, | |
"line": error.lineno, | |
"column": error.colno, | |
"message": error.message, | |
"stacktrace": error.stack | |
} | |
})); | |
} | |
catch (ex) { | |
if (window.console && window.console.error) { | |
console.error("Error reporting errors!"); | |
console.error(ex); | |
} | |
if (callback && typeof (callback) === "function") { | |
callback(); | |
} | |
} | |
} | |
var interceptAll = false; | |
if (window.addEventListener !== undefined) { | |
var mustUseObject = false; | |
try { | |
window.addEventListener("test", null, Object.defineProperty({}, "capture", { get: function () { mustUseObject = true; } })); | |
} catch (_) { | |
} | |
window.addEventListener("error", function (e) { | |
reportError(e, loadNoJs); | |
}, mustUseObject ? { "passive": true, "capture": interceptAll } : true); | |
} | |
else if (window.attachEvent !== undefined) { | |
window.attachEvent("onerror", reportError); | |
} | |
else if (window.onerror !== undefined) { | |
window.onerror = function (msg, source, lineno, colno, error) { | |
reportError({ | |
filename: source, | |
lineno: lineno, | |
colno: colno, | |
message: msg, | |
error: error | |
}, loadNoJs); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment