Skip to content

Instantly share code, notes, and snippets.

@mqudsi
Last active May 18, 2023 01:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mqudsi/2f570cf58d7d293ba27217a308659dfe to your computer and use it in GitHub Desktop.
Save mqudsi/2f570cf58d7d293ba27217a308659dfe to your computer and use it in GitHub Desktop.
Client-side JavaScript error reporting library, compatible with ancient browsers.
// 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