How do I overwrite the global Exception handler in JavaScript so that it becomes the top level handler for all uncaught exceptions?
window.onerror didn’t work. The code is:
<HTML>
<HEAD>
<script language='javascript'>
window.onerror = function (em, url, ln) {
alert(em + ", " + url + ", " + ln);
return false;
}
function fGo() {
try
{
var a = b; // Error here: b not defined
}
catch (e)
{
throw e;
}
}
</script>
</HEAD>
<BODY>
<button onclick='fGo()'>GO</button>
</BODY>
</HTML>
I'm testing on Chrome, by the way. The developer console registers the uncaught exception, but the alert() in window.onerror does not appear.
As of 2013, Chrome supports the window.onerror. (I have version 25, and comments imply earlier versions as well.)
I wrapped jQuery using currying to create a proxy that always does a try...catch in the jQuery functions.
I use it in www.js-analytics.com. However, the solution only holds for jQuery scripts.
Before 2013 Google Chrome didn't support window.onerror, and apparently it wasn't implemented in WebKit.
window.onerror = function(errorMsg, url, lineNumber) {
// Code to run when an error has occurred on the page
}
Chrome support for window.onerror
I believe support started in Chrome v10 (Chromium Issue 7771), but it looks as if "full" support with CORS support was resolved around Chrome 30+ (Chromium Issue 159566)
caniuse.com doesn't currently track this JavaScript feature (GitHub Issue 11999) ... to add support to this issue, log in to GitHub and "react" with a "Thumbs Up" on the original post (don't +1 in comments).
Current Google documentation for window.onerror
Chrome DevTools ~ Handle runtime exceptions using window.onerror
Perhaps you're looking for window.onerror. I am not sure whether this is available on all browsers.
Related
My site is http://www.thetruenorth.co.uk/
I can't get JQuery to work on my site in IE9 down. It works fine in every other browser.
I've realised that it is the code below, which detects if it's a small screen (mobile), that stops it from working. If I remove this bit, everything works. I use this because I don't know how else I'd disable JS for mobiles, but keep it for desktop. Suggestions welcome.
$(document).ready(function(){
if(matchMedia('only screen and (max-width: 1023px)').matches)
{}
else {
CODE HERE
}
});
I have a feeling there's a bug or something that I'm not aware of. Please could someone put me out of my misery?
Thanks
Simple Debugging in IE9
Open IE9
Press F12 to open the Developer window
Click the 'Script' tab
Click 'Console' on the right pane
Attempt to load your page
You will see the following error:
SCRIPT5009: 'matchMedia' is undefined
scripts.js, line 2 character 2
IE9 does not support the 'matchMedia' function and thus does not define it. Attempting to reference it in code stops the execution of the JavaScript completely at that point because it doesn't know what to do with a reference to something that is undefined.
What is going on
jQuery is loading on your page. You can confirm this by typing '$' into the text input line below the console output and press enter. The console will output some data about how $ is defined. This is a very good sign that jQuery loaded. It isn't conclusive in all situations, but for this one we are set.
What is happening is that your callback that is running onDomReady (via $(document).ready(...)), but it is erroring on the very first line. This error causes the rest of the callback to not execute.
Verifying Functionality Support
You can use caniuse.com to check to see what browsers support functionality (JS, CSS, etc). In this case: http://caniuse.com/matchmedia. You will note that IE10 is the first version that supports the matchMedia function. You can assume that in any earlier version you will not have matchMedia by default and referencing it will cause errors.
What You Can Do Now
On the caniuse.com site, at the top is a horizontal list titled "Resources". In this area you will generally find ways to patch browsers that do not support specific functionality.
In the case of matchMedia there is a link to a 'polyfill' which will use custom js to emulate the functionality of matchMedia. The url is: https://github.com/paulirish/matchMedia.js/.
Polyfills sometimes have limitations or catches to using them so be careful. It is also interesting to note that the matchMedia polyfill was written by Paul Irish, who is a very public figure for web technologies.
A Note On Conditional IE Includes
IE supports conditional comments, so you can include the polyfill defined above only for specific versions of IE; in your case anything < IE10. This is documented on the MDN here: http://msdn.microsoft.com/library/ms537512.aspx
<!--[if lte IE 10]]>
<script src="polyfill.js"></script>
<![endif]-->
This is done so that we can use the browser's implementation when possible (generally faster and potentially with more functionality) and polyfill only when needed.
j08691 found the problem you have.
If you need matchMedia to work with IE9 and down, or Firefox 6 and down or Safari 5.1 and down you must shim it. Here is a polyfill for matchMedia which will let you use it on older browsers.
Note, this is not a jQuery issue, this issue is with matchMedia browser support
That's because matchMedia only works with IE10.
Ref: https://developer.mozilla.org/en-US/docs/DOM/window.matchMedia
You may be better off doing this with PHP. ie probably isn't able to run matchMedia correctly. I always keep things like that on the server side because that'll run the same for any client. If you're using PHP try get_browser(). Really easy to write a quick if statement. Check the examples if you need help.
Andrew Martinez's answer is fairly thorough and correct, and I personally found it to be very useful.
The markup for getting the matchMedia method in IE9 would look as follows
<![if lt IE 10]>
<script src="scripts/matchMedia.js"></script>
<![endif]>
I just check if the browser is Chrome or not and then add the matchMedia code from github, have a look below:
$(document).ready(function() {
var isChrome = !!window.chrome;
if (isChrome == true) {
//do this for chrome
} else if (isChrome != true) {
//do this for all other browsers including IE
//so copy and paste current matchMedia.js script form here https://github.com/paulirish/matchMedia.js/blob/master/matchMedia.js like below
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. Dual MIT/BSD license */
window.matchMedia || (window.matchMedia = function() {
"use strict";
// For browsers that support matchMedium api such as IE 9 and webkit
var styleMedia = (window.styleMedia || window.media);
// For those that don't support matchMedium
if (!styleMedia) {
var style = document.createElement('style'),
script = document.getElementsByTagName('script')[0],
info = null;
style.type = 'text/css';
style.id = 'matchmediajs-test';
script.parentNode.insertBefore(style, script);
// 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers
info = ('getComputedStyle' in window) && window.getComputedStyle(style, null) || style.currentStyle;
styleMedia = {
matchMedium: function(media) {
var text = '#media ' + media + '{ #matchmediajs-test { width: 1px; } }';
// 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers
if (style.styleSheet) {
style.styleSheet.cssText = text;
} else {
style.textContent = text;
}
// Test if media query is true or false
return info.width === '1px';
}
};
}
return function(media) {
return {
matches: styleMedia.matchMedium(media || 'all'),
media: media || 'all'
};
};
}());
//below you can add your own matchMedia code
}
});
It fails after doing this:
<script type="text/javascript" src="/js/dojo-release-1.7.2-src/dojo/dojo.js"></script>
throwing an error on the statement (in this version, 1.7.2, it is line 260)
return new XMLHttpRequest();
being: "TypeError: Object doesn't support this method or property"
The silly thing is that this line is execute a lot of times (maybe even more than 100) without any problem, and it doesn't seem to be dependent on any variables. Unfortunately, at some point it fails. I swapped the line with:
try{
foo = new window.XMLHttpRequest();
return foo;
} catch(e) {
console.log("OUCH, ERROR.");
console.log(typeof window.XMLHttpRequest);
console.log(e);
}
which outputs:
OUCH ERROR.
object
TypeError: Object doesn't support this method or property
I am quite lost, as window.XMLHttpRequest seems to be an object, why can't I 'new' it? Any suggestion on how to debug this would be welcome.
What I find absolutely confusing is that this error only occurs when I go to this page using a link. when I refresh the page using F5, everything works, no errors, nothing.
Moreover, it runs flawless in internet explorer 9, firefox and chrome.
Clear cache completely in-browser
remove any components you have (activex) which are not native
if still issues
run xml-validation on your HTML
make sure the DOCTYPE is correct
check for selfclosing / non-closed tags
How can I break on error?
I have a code:
throw new Error("Some error");
And I'm using most recent version of Web Inspector (Webkit) and Firebug(Mozilla). These tools catch and print the error, but does not break. May I don't know the how to. Please let me know how can I to do these?
In WebKit you need to click this to enable break on error. If you click it again it will also break on warnings and clicking it again will disable it.
alt text http://a.yfrog.com/img832/3580/screenshot20100723at101.png
I redefined Error to get solution.
var Error = function(v)
{
console.trace();
console.debug(v);
}
This solved my problem.
Is there a console logger for IE? I'm trying to log a bunch of tests/assertions to the console but I can't do this in IE.
You can access IE8 script console by launching the "Developer Tools" (F12). Click the "Script" tab, then click "Console" on the right.
From within your JavaScript code, you can do any of the following:
<script type="text/javascript">
console.log('some msg');
console.info('information');
console.warn('some warning');
console.error('some error');
console.assert(false, 'YOU FAIL');
</script>
Also, you can clear the Console by calling console.clear().
NOTE: It appears you must launch the Developer Tools first then refresh your page for this to work.
Since version 8, Internet Explorer has its own console, like other browsers. However, if the console is not enabled, the console object does not exist and a call to console.log will throw an error.
Another option is to use log4javascript (full disclosure: written by me), which has its own logging console that works in all mainstream browsers, including IE >= 5, plus a wrapper for the browser's own console that avoids the issue of an undefined console.
Extremely important if using console.log() in production:
if you end up releasing console.log() commands to production you need to put in some kind of fix for IE - because console is only defined when in F12 debugging mode.
if (typeof console == "undefined") {
this.console = { log: function (msg) { alert(msg); } };
}
[obviously remove the alert(msg); statement once you've verified it works]
See also 'console' is undefined error for Internet Explorer for other solutions and more details
There is Firebug Lite which gives a lot of Firebug functionality in IE.
Simple IE7 and below shim that preserves Line Numbering for other browsers:
/* console shim*/
(function () {
var f = function () {};
if (!window.console) {
window.console = {
log:f, info:f, warn:f, debug:f, error:f
};
}
}());
In his book, "Secrets of Javascript Ninja", John Resig (creator of jQuery) has a really simple code which will handle cross-browser console.log issues. He explains that he would like to have a log message which works with all browsers and here is how he coded it:
function log() {
try {
console.log.apply(console, arguments);
} catch(e) {
try {
opera.postError.apply(opera, arguments);
}
catch(e) {
alert(Array.prototype.join.call( arguments, " "));
}
}
For IE8 or console support limited to console.log (no debug, trace, ...) you can do the following:
If console OR console.log undefined: Create dummy functions for
console functions (trace, debug, log, ...)
window.console = {
debug : function() {}, ...};
Else if console.log is defined (IE8) AND console.debug (any other) is not defined: redirect all logging functions to console.log, this allows to keep those logs !
window.console = {
debug : window.console.log, ...};
Not sure about the assert support in various IE versions, but any suggestions are welcome.
You can use cross-browser wrapper: https://github.com/MichaelZelensky/log.js
For older version of IE (before IE8), it is not straight forward to see the console log in IE Developer Toolbar, after spending hours research and trying many different solutions, finally, the following toolbar is great tool for me:
http://www.my-debugbar.com/wiki/CompanionJS/Installing
The main advantage of this is providing a console for IE6 or IE7, so you can see what are the error (in the console log)
Note:
It is free
screen shot of the toolbar
I've been always doing something like this:
var log = (function () {
try {
return console.log;
}
catch (e) {
return function () {};
}
}());
and from that point just always use log(...), don't be too fancy using console.[warn|error|and so on], just keep it simple. I usually prefer simple solution then fancy external libraries, it usually pays off.
simple way to avoid problems with IE (with non existing console.log)
Is it possible to add messages to the built-in error console of Firefox from JavaScript code running in web pages?
I know that I there's Firebug, which provides a console object and its own error console, but I was looking for a quick fix earlier on and couldn't find anything.
I guess it might not be possible at all, to prevent malicious web pages from spamming the log?
If you define a global function that checks for the existence of window.console, you can use Firebug for tracing and still plays nice with other browsers and/or if you turn Firebug's console tracing off:
debug = function (log_txt) {
if (typeof window.console != 'undefined') {
console.log(log_txt);
}
}
debug("foo!");
You cannot write to the console directly from untrusted JavaScript (e.g. scripts coming from a page). However, even if installing Firebug does not appeal to you, I'd recommend checking out Firebug Lite, which requires no installation into the browser (nor, in fact, does it even require Firefox). It's a script which you can include into any web page (even dynamically), which will give you some basic Firebug functionality (such as console.log()).
Yes, you can =P
function log(param){
setTimeout(function(){
throw new Error("Debug: " + param)
},0)
}
//Simple Test:
alert(1)
log('This is my message to the error log -_-')
alert(2)
log('I can do this forever, does not break')
alert(3)
Update to a real function
This is a simple hack, just for fun.
window.console is undefined in Firefox 4 beta 6 even if Firebug 1.6X.0b1 is enabled and open, probably because of privilege issues that others discuss. However, Firefox 4 has a new Tools > Web Console, and if this is open you have a window.console object and untrusted JavaScript code on the page can use console.log(). The Web Console is in flux (see https://wiki.mozilla.org/Firefox/Projects/Console), you may need to change settings named devtools.* in about:config , YMMV.
I would just install Firebug and use console.log. If you can't do that, though, you can always throw an error:
throw "foobar";
throw new Error("bazquux");
Of course, this will break you out of the code that you're currently executing, so you can't use it for detailed logging, but if you can work around that I think it's the only way to get something logged out of the box.
AFAIK, it is not possible. But if you are interested in how extensions in Firefox interact with the error console, check this out.
This function does not require any extension nor library. However it grants full privileges to the relevant website. No worries since you are the one developing it, right?
// Define mylog() function to log to Firefox' error console if such a
// thing exists
function defineMyLog()
{
// Provide a useless but harmless fallback
mylog = function(msg) { };
// return; // disable in production
if (typeof(netscape) === "undefined") {
// alert("Logging implemented only for Firefox");
return;
}
// The initial auth popup can be avoided by pre-setting some magic user_pref
// ( "capability.principal.codebase.p0.granted", "UniversalXPConnect"), etc.
try {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
} catch (e) { // User has denied privileges
// alert(e.name + ": " + e.message);
return;
}
ffconsoleService = Components.classes["#mozilla.org/consoleservice;1"]
.getService(Components.interfaces.nsIConsoleService);
mylog = function (msg)
{
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
ffconsoleService.logStringMessage(new Date().toLocaleTimeString() + ": " + msg);
}
mylog("Firefox logging function has been defined");
// window.open("javascript:"); // this URL does not work anymore?
}
If you're interested, check out a script I wrote -- it's a "cheap" Firebug replacement that doesn't interfere with any normal console (like Safari or Chrome) but does extend it with almost all the Firebug methods:
http://code.google.com/p/glentilities/
Look under the hood and you'll see what I mean by "cheap". :-)
Combine it with YUI or json.org's JSON serializers to sorta replicate console.dir.
Firebug and Firebug Lite are definitely nicer GUIs, but I use my home-grown one all the time to retain logging safely even for production code -- without constant commenting & un-commenting,