aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Minar2013-08-21 22:57:48 -0700
committerIgor Minar2013-08-24 12:49:46 -0700
commit5d9f42050a11015adbd5dc4dde73818919e93a99 (patch)
tree0d9096b863ff8add148e8ad180816b1937c28ad3
parent80d0f98263786ef302ca7551c4515560a7c07195 (diff)
downloadangular.js-5d9f42050a11015adbd5dc4dde73818919e93a99.tar.bz2
fix($q): reject should catch & forward exceptions thrown in errback
-rw-r--r--src/ng/q.js7
-rw-r--r--test/ng/qSpec.js20
2 files changed, 25 insertions, 2 deletions
diff --git a/src/ng/q.js b/src/ng/q.js
index cc39967c..6c4d3f5f 100644
--- a/src/ng/q.js
+++ b/src/ng/q.js
@@ -375,7 +375,12 @@ function qFactory(nextTick, exceptionHandler) {
then: function(callback, errback) {
var result = defer();
nextTick(function() {
- result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
+ try {
+ result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
+ } catch(e) {
+ result.reject(e);
+ exceptionHandler(e);
+ }
});
return result.promise;
}
diff --git a/test/ng/qSpec.js b/test/ng/qSpec.js
index 7c949602..28be0405 100644
--- a/test/ng/qSpec.js
+++ b/test/ng/qSpec.js
@@ -950,6 +950,15 @@ describe('q', function() {
syncResolve(deferred, rejectedPromise.then());
expect(log).toEqual(['error(rejected)->reject(rejected)']);
});
+
+
+ it('should catch exceptions thrown in errback and forward them to derived promises', function() {
+ var rejectedPromise = q.reject('rejected');
+ rejectedPromise.then(null, error('Broken', 'catch me!', true)).
+ then(null, error('Affected'))
+ mockNextTick.flush();
+ expect(log).toEqual(['errorBroken(rejected)->throw(catch me!)', 'errorAffected(catch me!)->reject(catch me!)']);
+ });
});
@@ -1460,7 +1469,7 @@ describe('q', function() {
deferred = q.defer();
});
-
+
afterEach(function() {
// Restore the original exception logging mode
mockNextTick.logExceptions = originalLogExceptions;
@@ -1468,6 +1477,15 @@ describe('q', function() {
it('should still reject the promise, when exception is thrown in success handler, even if exceptionHandler rethrows', function() {
+ deferred.promise.then(function() { throw 'reject'; }).then(null, errorSpy);
+ deferred.resolve('resolve');
+ mockNextTick.flush();
+ expect(exceptionExceptionSpy).toHaveBeenCalled();
+ expect(errorSpy).toHaveBeenCalled();
+ });
+
+
+ it('should still reject the promise, when exception is thrown in error handler, even if exceptionHandler rethrows', function() {
deferred.promise.then(null, function() { throw 'reject again'; }).then(null, errorSpy);
deferred.reject('reject');
mockNextTick.flush();