Does Javascript fire an event for unhandled/uncaught exceptions? - javascript

I'm looking to log unhandled javascript exceptions. Is there an event that fires when an exception isn't caught? I'm looking to catch the exceptions before they cause javascript errors in the browser, but I'd rather not run my entire application inside of a try/catch. Any help would be appreciated. Thanks!
Update:
tvanfosson pointed out onerror as a possibility. It is not part of a spec and is only available in IE or Gecko based browsers.
For more information - http://books.google.com/books?id=tKszhx-XkzYC&pg=PA386&lpg=PA386&dq=safari+onerror+javascript&source=web&ots=gQaGbpUnjG&sig=iBCtOQs0aH_EAzSbWlGa9v5flyo#PPA387,M1
OnError Support Table - http://www.quirksmode.org/dom/events/error.html
Mozilla's documentation - https://developer.mozilla.org/en/DOM/window.onerror
WebKit Bug Report - https://bugs.webkit.org/show_bug.cgi?id=8519

Check out this Fiddle:
http://jsfiddle.net/xYsRA/1/
window.onerror = function (msg, url, line) {
console.log("Caught[via window.onerror]: '" + msg + "' from " + url + ":" + line);
return true; // same as preventDefault
};
window.addEventListener('error', function (evt) {
console.log("Caught[via 'error' event]: '" + evt.message + "' from " + evt.filename + ":" + evt.lineno);
console.log(evt); // has srcElement / target / etc
evt.preventDefault();
});
throw new Error("Hewwo world. I crash you!!!");
throw new Error("Hewwo world. I can only crash you once... :(");
Which prints:
Caught[via window.onerror]: 'Uncaught Error: Hewwo world. I crash you!!!' from http://fiddle.jshell.net/xYsRA/1/show/:32 fiddle.jshell.net:21
Caught[via 'error' event]: 'Uncaught Error: Hewwo world. I crash you!!!' from http://fiddle.jshell.net/xYsRA/1/show/:32 fiddle.jshell.net:26
ErrorEvent {lineno: 32, filename: "http://fiddle.jshell.net/xYsRA/1/show/", message: "Uncaught Error: Hewwo world. I crash you!!!", clipboardData: undefined, cancelBubble: false…}
fiddle.jshell.net:27\
Notes:
If you remove the "return true" / "evt.preventDefault()" lines, then after the error is logged, it will print on the JS console in the normal way.
Contrary to statements made above, window.onerror worked in all the browsers I tested. However, the addEventListener method is probably better anyways and provides richer semantics.

Try using an onerror handler. Docs from MDN. This will allow you to do something when an error is detected, but probably won't let you continue in a graceful way that a try/catch block would. Be aware that are undoubtedly differences between browsers in how this is handled.

Related

wkhtmltopdf and the jQuery.ready() function

I've been trying to generate a PDF using the wkhtmltopdf tool (http://wkhtmltopdf.org/). The page from which I want to generate a PDF using jQuery and has some initializations using a jQuery.ready() function, something like this:
jQuery(function() {
// do something
});
However, when I try to generate a PDF from the page the script is not executed. I've tried setting a delay to wait for the JavaScript to be executed with the option:
--javascript-delay 30000
But the result is the same.
When I've enabled wkhtmltopdf's JavaScript debugging option I get a warning, which I'm not sure if it's related to the problem:
Warning: undefined:0 TypeError: 'null' is not an object
Has anyone encountered this problem? Is there some kind of workaround?
EDIT: Seems the problem is caused by the error Warning: undefined:0 TypeError: 'null' is not an object. I've managed to print the error on the PDF using:
window.onerror = function(error, url, line) {
$('body').before('<b> Error: ' + error + '</b> <br />');
$('body').before('<b> Url: ' + url + '</b> <br />');
$('body').before('<b> Line: ' + line + '</b> <br />');
console.log(error, ' ', url, ' ', line);
};
But the information is very limited and I have no idea what might cause it:
Error: TypeError: 'null' is not an object
Url: undefined
Line: 0
The problem turned out to be that Qt doesn't support localStorage, so one of the initialization scripts failed which cause the jQuery.ready() not being executed.
I've managed to debug it with a browser with Qt support: QtWeb. (Tried Arora as well, couldn't run it on my system).

Improving our javascript error reporting

So right now we have some generic code to report errors either from our code or third party code. Our project is a JQM/Phonegap project for iOS. What is happening is we pretty much always get the same useless error... TypeError: 'undefined' is not a function... with no line number or other helpful information. Is there a way I could change the code to maybe get WHAT is undefined or WHERE it is?
window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
//Handle errors not in a jquery event handler
//DebugMessage(errorMSg + " "+ url + " " + lineNumber);
var ex = new Error(errorMsg, url, lineNumber);
HandleError(ex, "window.onerror");
//HandleError sends the error object to
//a webservice to log the error.
return true;
};
Any tips on debugging javascript errors would help as well.
In recent months, browsers have extended the signature of window.onerror to provide more information.
window.onerror = function(msg, file, line, col, error) {
// backwards compat
if (!error) {
error = new Error(msg);
}
// send error to your logger
}
This should give you a lot more information. But there are still things where you need better context. You should check out some third-party tools for this like TrackJS that automatically give you this, plus extra information on how the error occurred.
Disclaimer: I am one of the original authors of TrackJS, so I know a bunch about JavaScript errors :)
Have you heard of Ripple? It is a mobile emulator for Chrome designed for testing PhoneGap applications.
That might help you find your errors before you debug on the devices.

Line and column in Javascript Error event attributes

I've decided that there are some errors which I don't want to go to the browser error handler. But I still want to know about them. In my actual code I have a function which stores the errors in a hidden element and ajax submits them to a database. Following is a simplified version of my try block:
try
{
newValueEvaled = eval(newValue);
}catch(err)
{
alert("Error caught: Line " + err.lineNumber + ((err.columnNumber != undefined)?', Column:' + err.columnNumber:"") + '\n' + err.message);
}
I'd like the columnNumber too. Currently it is never there, but somehow the browser error console has access to it. Can anyone tell me how I can get access to it as well?
I'm almost certain it's not possible to get the error column number from JavaScript running in the page. Firebug/WebKit console/IE console has access to internal browser objects that provide more information about the call stack than is available to code running inside the page.
You can access the error line and possibly column using a custom error handler function:
function dumpErrors(error, file, line, column)
{
alert('Error: ' + error + ', occurred in file: ' + file + ', on line: ' + line + ', at column: ' + (column || 'unknown'));
}
onerror = dumpErrors;
The «line» is available for all browsers. For the «column», it seems it's available on latest Chrome (release 30.0+), but not on Firefox (release 17, running on my Linux).

Is there a way to try/catch an entire page dynamically?

I have a page on which mysterious JavaScript errors keep popping up. They appear to be coming from the application we use and do not own the source for. I'm working on a real solution to this issue, but we have a demo tomorrow and I was wondering if there is a way to just suppress JS errors page wide (like wrapping ALL the javascript components in a giant try catch).
You could add a handler to the window.onerror event. In this case, all the errors that occur inside the window will be redirected to the handler of this event. (I did test this in Firefox and it worked, but I was having trouble with it in Chrome - my Chrome installation is pretty messed up, so that could be the problem, but there are Chromium bugs filed that relate to this issue: bug #7771 and bug #8939)
window.onerror = function (msg, url, line) {
alert("Error on line " + line + " in " + url + ":\n" + msg);
// return true to prevent browser from displaying error
return true;
}

JavaScript exception handling - displaying the line number

When catching / handling exceptions in JavaScript, how can I determine what the call stack was when the exception occurred? (and also if possible what the line number was)
try
{
// etc...
}
catch (ex)
{
// At this point here I want to be able to print out a detailed exception
// message, complete with call stack, and if possible line numbers.
}
Each browser handles this differently, so there isn't a universal way to do it. This blog post has some good code to dump a stack trace for most supported browsers. I don't think there is a good way to provide the line number.
If you're looking to debug one function in particular, Firebug has a good stack trace function (vis console.trace()).
Have a look at this.
A way to analyse the available information:
try
{
doInit();
} catch(err)
{
var vDebug = "";
for (var prop in err)
{
vDebug += "property: "+ prop+ " value: ["+ err[prop]+ "]\n";
}
vDebug += "toString(): " + " value: [" + err.toString() + "]";
status.rawValue = vDebug;
}
I've discovered that in JavaScript running under IE it is not possible to capture a stack trace at the point that an exception is caught. According to this PDF the only way of getting a stack trace in IE is if you don't handle the exception.
With most errors, you can examine the stack trace, which will include the line and column number of the error location:
try {
throw new Error('foo');
} catch(e) {
console.log(e.message);
console.log(e.stack);
const [, lineno, colno] = e.stack.match(/(\d+):(\d+)/);
console.log('Line:', lineno);
console.log('Column:', colno);
}
This line 13 is correct, because that is the line in the HTML where the error came from in the response from stacksnippets.net:
Note that this will not work for non-errors thrown, like throw null or throw 'foo' (which are not recommended for precisely this reason).

Categories

Resources