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

Commit 0462b68

Browse files
committed
chore($q): replace plain TypeError with minErr+TypeError in cyclical resolve check
1 parent 1b331f3 commit 0462b68

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

docs/content/error/$q/qcycle.ngdoc

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
@ngdoc error
2+
@name $q:qcycle
3+
@fullName Cannot resolve a promise with itself
4+
@description
5+
6+
Occurs when resolving a promise with itself as the value, including returning the promise in a
7+
function passed to `then`. The A+ 1.1 spec mandates that this behavior throw a TypeError.
8+
https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
9+
10+
```
11+
var promise = $q.defer().promise;
12+
13+
//bad
14+
promise.then(function (val) {
15+
//Cannot return self
16+
return promise;
17+
});
18+
19+
//good
20+
promise.then(function (val) {
21+
return 'some other value';
22+
});
23+
```

src/ng/q.js

+11-3
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ function $$QProvider() {
235235
* @returns {object} Promise manager.
236236
*/
237237
function qFactory(nextTick, exceptionHandler) {
238-
var $qMinErr = minErr('$q');
238+
var $qMinErr = minErr('$q', TypeError);
239239
function callOnce(self, resolveFn, rejectFn) {
240240
var called = false;
241241
function wrap(fn) {
@@ -338,8 +338,16 @@ function qFactory(nextTick, exceptionHandler) {
338338
Deferred.prototype = {
339339
resolve: function(val) {
340340
if (this.promise.$$state.status) return;
341-
if (val === this.promise) throw new TypeError('Cycle detected');
342-
this.$$resolve(val);
341+
if (val === this.promise) {
342+
this.$$reject($qMinErr(
343+
'qcycle',
344+
"Expected promise to be resolved with value other than itself '{0}'",
345+
val));
346+
}
347+
else {
348+
this.$$resolve(val);
349+
}
350+
343351
},
344352

345353
$$resolve: function(val) {

test/ng/qSpec.js

+14
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,20 @@ describe('q', function() {
815815
});
816816

817817

818+
it('should complain if promise fulfilled with itself', function() {
819+
var resolveSpy = jasmine.createSpy('resolve');
820+
var rejectSpy = jasmine.createSpy('reject');
821+
promise.then(resolveSpy, rejectSpy);
822+
deferred.resolve(deferred.promise);
823+
mockNextTick.flush();
824+
825+
expect(resolveSpy).not.toHaveBeenCalled();
826+
expect(rejectSpy).toHaveBeenCalled();
827+
expect(rejectSpy.calls[0].args[0].message).
828+
toMatch(/\[\$q\:qcycle\] Expected promise to be resolved with value other than itself/);
829+
});
830+
831+
818832
it('should do nothing if a promise was previously resolved', function() {
819833
promise.then(success(), error());
820834
expect(logStr()).toBe('');

0 commit comments

Comments
 (0)