Skip to content

Commit

Permalink
Deferred: Give better stack diagnostics on exceptions
Browse files Browse the repository at this point in the history
Ref gh-2736

The exception stack has the name of the immediately outer function where the
exception occurred, which can be very handy for tracing errors. Since we already
have the exception object we might as well use it.
  • Loading branch information
dmethvin committed May 12, 2016
1 parent b8bd481 commit 07c11c0
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/deferred/exceptionHook.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jQuery.Deferred.exceptionHook = function( error, stack ) {
// Support: IE 8 - 9 only
// Console exists when dev tools are open, which can happen at any time
if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
window.console.warn( "jQuery.Deferred exception: " + error.message, stack );
window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
}
};

Expand Down
25 changes: 16 additions & 9 deletions test/unit/deferred.js
Original file line number Diff line number Diff line change
Expand Up @@ -542,28 +542,30 @@ QUnit.test( "jQuery.Deferred.then - spec compatibility", function( assert ) {
} catch ( _ ) {}
} );

// Test fails in IE9 but is skipped there because console is not active
QUnit[ window.console ? "test" : "skip" ]( "jQuery.Deferred.exceptionHook", function( assert ) {

assert.expect( 1 );
assert.expect( 2 );

var done = assert.async(),
defer = jQuery.Deferred(),
oldWarn = window.console.warn;

window.console.warn = function( msg ) {
window.console.warn = function() {

// Support: Chrome <=41 only
// Some Chrome versions newer than 30 but older than 42 display the "undefined is
// not a function" error, not mentioning the function name. This has been fixed
// in Chrome 42. Relax this test there.
// This affects our Android 5.0 & Yandex.Browser testing.
var oldChromium = false;
var msg = Array.prototype.join.call( arguments, " " ),
oldChromium = false;
if ( /chrome/i.test( navigator.userAgent ) ) {
oldChromium = parseInt(
navigator.userAgent.match( /chrome\/(\d+)/i )[ 1 ], 10 ) < 42;
}
if ( oldChromium ) {
assert.ok( /(?:barf|undefined)/.test( msg ), "Message: " + msg );
assert.ok( /(?:barf|undefined)/.test( msg ), "Message (weak assertion): " + msg );
} else {
assert.ok( /barf/.test( msg ), "Message: " + msg );
}
Expand All @@ -580,14 +582,17 @@ QUnit[ window.console ? "test" : "skip" ]( "jQuery.Deferred.exceptionHook", func
// Should NOT get an error
throw new Error( "Make me a sandwich" );
} ).then( null, jQuery.noop )
).then( function( ) {
).then( function barf( ) {
jQuery.thisDiesToo();
} ).then( null, function( ) {
window.console.warn = oldWarn;
done();
} );

defer.resolve();
} );

// Test fails in IE9 but is skipped there because console is not active
QUnit[ window.console ? "test" : "skip" ]( "jQuery.Deferred.exceptionHook with stack hooks", function( assert ) {

assert.expect( 2 );
Expand All @@ -605,24 +610,26 @@ QUnit[ window.console ? "test" : "skip" ]( "jQuery.Deferred.exceptionHook with s
return "NO STACK FOR YOU";
};

window.console.warn = function( msg, stack ) {
window.console.warn = function() {

// Support: Chrome <=41 only
// Some Chrome versions newer than 30 but older than 42 display the "undefined is
// not a function" error, not mentioning the function name. This has been fixed
// in Chrome 42. Relax this test there.
// This affects our Android 5.0 & Yandex.Browser testing.
var oldChromium = false;
var msg = Array.prototype.join.call( arguments, " " ),
oldChromium = false;
if ( /chrome/i.test( navigator.userAgent ) ) {
oldChromium = parseInt(
navigator.userAgent.match( /chrome\/(\d+)/i )[ 1 ], 10 ) < 42;
}
if ( oldChromium ) {
assert.ok( /(?:cough_up_hairball|undefined)/.test( msg ), "Function mentioned: " + msg );
assert.ok( /(?:cough_up_hairball|undefined)/.test( msg ),
"Function mentioned (weak assertion): " + msg );
} else {
assert.ok( /cough_up_hairball/.test( msg ), "Function mentioned: " + msg );
}
assert.ok( /NO STACK FOR YOU/.test( stack ), "Stack trace included: " + stack );
assert.ok( /NO STACK FOR YOU/.test( msg ), "Stack trace included: " + msg );
};
defer.then( function() {
jQuery.cough_up_hairball();
Expand Down

0 comments on commit 07c11c0

Please sign in to comment.