Skip to content

Commit

Permalink
fix($q): Add traceback to unhandled promise rejections, Fixes: angula…
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Grainger committed Dec 20, 2016
1 parent 4e143fc commit c014f10
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 40 deletions.
6 changes: 5 additions & 1 deletion src/ng/q.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,11 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
if (!toCheck.pur) {
toCheck.pur = true;
var errorMessage = 'Possibly unhandled rejection: ' + toDebugString(toCheck.value);
exceptionHandler(errorMessage);
if (toCheck.value instanceof Error) {
exceptionHandler(toCheck.value, errorMessage);
} else {
exceptionHandler(errorMessage);
}
}
}
}
Expand Down
100 changes: 61 additions & 39 deletions test/ng/qSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,16 +181,14 @@ describe('q', function() {
};


function exceptionHandler(reason) {
exceptionHandlerCalls.push(reason);
}


function exceptionHandlerStr() {
return exceptionHandlerCalls.join('; ');
function exceptionHandler(exception, reason) {
if (typeof reason === 'undefined') {
exceptionHandlerCalls.push({ reason: exception });
} else {
exceptionHandlerCalls.push({ reason: reason, exception: exception });
}
}


beforeEach(function() {
q = qFactory(mockNextTick.nextTick, exceptionHandler, true);
q_no_error = qFactory(mockNextTick.nextTick, exceptionHandler, false);
Expand Down Expand Up @@ -2167,45 +2165,69 @@ describe('q', function() {


describe('when exceptionHandler is called', function() {
it('should log an unhandled rejected promise', function() {
var defer = q.defer();
defer.reject('foo');
mockNextTick.flush();
expect(exceptionHandlerStr()).toBe('Possibly unhandled rejection: foo');
});
var exceptionEg = new Error('Fail');
var exceptionStr = toDebugString(exceptionEg);
var fixtures = [
{
type: 'exception',
value: exceptionEg,
expected: {
exception: exceptionEg,
reason: 'Possibly unhandled rejection: ' exceptionStr
}
},
{
type: 'plain value',
value: 'foo',
expected: {
reason: 'Possibly unhandled rejection: foo'
}
}
];
forEach(fixtures, function(fixture) {
var type = fixture.type;
var value = fixture.value;
var expected = fixture.expected;
it('should log an unhandled' + type + ' rejected promise', function() {
var defer = q.defer();
defer.reject(value);
mockNextTick.flush();
expect(exceptionHandlerCalls).toEqual([expected]);
});


it('should not log an unhandled rejected promise if disabled', function() {
var defer = q_no_error.defer();
defer.reject('foo');
expect(exceptionHandlerStr()).toBe('');
});
it('should not log an unhandled' + type + ' rejected promise if disabled', function() {
var defer = q_no_error.defer();
defer.reject(value);
expect(exceptionHandlerCalls).toEqual([]);
});


it('should log a handled rejected promise on a promise without rejection callbacks', function() {
var defer = q.defer();
defer.promise.then(noop);
defer.reject('foo');
mockNextTick.flush();
expect(exceptionHandlerStr()).toBe('Possibly unhandled rejection: foo');
});
it('should log a handled' + type + ' rejected promise on a promise without rejection callbacks', function() {
var defer = q.defer();
defer.promise.then(noop);
defer.reject(value);
mockNextTick.flush();
expect(exceptionHandlerCalls).toEqual([expected]);
});


it('should not log a handled rejected promise', function() {
var defer = q.defer();
defer.promise.catch(noop);
defer.reject('foo');
mockNextTick.flush();
expect(exceptionHandlerStr()).toBe('');
});
it('should not log a handled' + type + 'rejected promise', function() {
var defer = q.defer();
defer.promise.catch(noop);
defer.reject(value);
mockNextTick.flush();
expect(exceptionHandlerCalls).toEqual([]);
});


it('should not log a handled rejected promise that is handled in a future tick', function() {
var defer = q.defer();
defer.promise.catch(noop);
defer.resolve(q.reject('foo'));
mockNextTick.flush();
expect(exceptionHandlerStr()).toBe('');
it('should not log a handled' + type + ' rejected promise that is handled in a future tick', function() {
var defer = q.defer();
defer.promise.catch(noop);
defer.resolve(q.reject(value));
mockNextTick.flush();
expect(exceptionHandlerCalls).toEqual([]);
});
});
});
});

0 comments on commit c014f10

Please sign in to comment.