Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 5d9f420

Browse files
committed
fix($q): reject should catch & forward exceptions thrown in errback
1 parent 80d0f98 commit 5d9f420

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

src/ng/q.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,12 @@ function qFactory(nextTick, exceptionHandler) {
375375
then: function(callback, errback) {
376376
var result = defer();
377377
nextTick(function() {
378-
result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
378+
try {
379+
result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
380+
} catch(e) {
381+
result.reject(e);
382+
exceptionHandler(e);
383+
}
379384
});
380385
return result.promise;
381386
}

test/ng/qSpec.js

+19-1
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,15 @@ describe('q', function() {
950950
syncResolve(deferred, rejectedPromise.then());
951951
expect(log).toEqual(['error(rejected)->reject(rejected)']);
952952
});
953+
954+
955+
it('should catch exceptions thrown in errback and forward them to derived promises', function() {
956+
var rejectedPromise = q.reject('rejected');
957+
rejectedPromise.then(null, error('Broken', 'catch me!', true)).
958+
then(null, error('Affected'))
959+
mockNextTick.flush();
960+
expect(log).toEqual(['errorBroken(rejected)->throw(catch me!)', 'errorAffected(catch me!)->reject(catch me!)']);
961+
});
953962
});
954963

955964

@@ -1460,14 +1469,23 @@ describe('q', function() {
14601469
deferred = q.defer();
14611470
});
14621471

1463-
1472+
14641473
afterEach(function() {
14651474
// Restore the original exception logging mode
14661475
mockNextTick.logExceptions = originalLogExceptions;
14671476
});
14681477

14691478

14701479
it('should still reject the promise, when exception is thrown in success handler, even if exceptionHandler rethrows', function() {
1480+
deferred.promise.then(function() { throw 'reject'; }).then(null, errorSpy);
1481+
deferred.resolve('resolve');
1482+
mockNextTick.flush();
1483+
expect(exceptionExceptionSpy).toHaveBeenCalled();
1484+
expect(errorSpy).toHaveBeenCalled();
1485+
});
1486+
1487+
1488+
it('should still reject the promise, when exception is thrown in error handler, even if exceptionHandler rethrows', function() {
14711489
deferred.promise.then(null, function() { throw 'reject again'; }).then(null, errorSpy);
14721490
deferred.reject('reject');
14731491
mockNextTick.flush();

0 commit comments

Comments
 (0)