-
Notifications
You must be signed in to change notification settings - Fork 27.4k
fix($timeout/$interval): do not trigger a digest when cancelling a $timeout/$interval #16064
Conversation
@@ -1328,8 +1328,7 @@ describe('ngAnimate $animateCss', function() { | |||
animator.end(); | |||
|
|||
expect(element.data(ANIMATE_TIMER_KEY)).toBeUndefined(); | |||
$timeout.flush(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an example of how this change can be "breaking" for some tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it's probably not a breaking change? Should we mention this in the review anyway? (But no under Breaking Changes)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jbedard Can you clarify how this can be "breaking"?
For now I have not removed the 2 |
Just saw that the unit tests failed with lots of compile test failures. |
src/ng/q.js
Outdated
@@ -378,8 +378,8 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) { | |||
// eslint-disable-next-line no-unmodified-loop-condition | |||
while (!queueSize && checkQueue.length) { | |||
var toCheck = checkQueue.shift(); | |||
if (!toCheck.pur) { | |||
toCheck.pur = true; | |||
if (isStateExceptionHandled(toCheck)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this must be !isStateExceptionHandled(toCheck)
and will fix all the failing tests except one
@@ -459,11 +459,12 @@ describe('ngModelOptions', function() { | |||
$rootScope.$watch(watchSpy); | |||
|
|||
helper.changeInputValueTo('a'); | |||
expect(function() {$browser.defer.flush();}).toThrowError('No deferred tasks to be flushed'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't work correctly. It still flushes the task and triggers a digest. I haven't found out why exactly it doesn't work, but I suspect it's because of a mismatch between the real browser and the mock browser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The assumption that there are no deferred tasks is wrong at this point, because there's obviously a pending timeout.
We just need to check that the watchFn doesn't get called.
If you put in this:
helper.changeInputValueTo('a');
$timeout.flush(2000);
helper.changeInputValueTo('b');
$timeout.flush(2000);
the test will fail without the patch. The second timeout.flush is crucial - without it, the watchFn spy doesn't get called, but with it, it gets called twice (without the patch).
Updated. Thanks for pointing out the issues @Narretz |
@@ -449,7 +449,7 @@ describe('ngModelOptions', function() { | |||
}); | |||
|
|||
|
|||
it('should not trigger digest while debouncing', function() { | |||
it('should not trigger digest while debouncing', inject(function($browser) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because it was calling $browser.defer.flush()
like the other tests (which is wrong in this case). I'll undo this...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
Previously `.catch(noop)` was used on the rejected timeout/interval to prevent an unhandled rejection error. However this would schedule a deferred task to run the `noop`. If the cancelling was outside a digest this could cause a new digest such as with the ng-model `debounce` option. Fixes angular#16057
Previously, `.catch(noop)` was used on a rejected timeout/interval to prevent an unhandled rejection error (introduced in #c9dffde1cb). However this would schedule a deferred task to run the `noop`. If the cancelling was outside a digest this could cause a new digest such as with the ng-model `debounce` option. For unit testing, this means that it's no longer necessary to use `$timeout.flush()` when a `$timeout` has been cancelled outside of a digest. Previously, this was necessary to execute the deferred task added by `.catch(noop). There's an example of such a change in this commit's changeset in the file `/test/ngAnimate/animateCssSpec.js`. Fixes #16057 Closes #16064
Would this have affected |
I don't think this would have changed the return value. Also doesn't look like |
Previously
.catch(noop)
was used on the rejected timeout/interval to prevent an unhandled rejection error. However this would schedule a deferred task to run thenoop
. If the cancelling was outside a digest this could cause a new digest such as with the ng-modeldebounce
option.Fixes #16057