-
Notifications
You must be signed in to change notification settings - Fork 27.4k
fix(ngEventDirs): check for $rootScope.$$phase in event handler and d… #14674
Conversation
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. |
1 similar comment
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. |
CLAs look good, thanks! |
1 similar comment
CLAs look good, thanks! |
@@ -65,6 +65,8 @@ forEach( | |||
}; | |||
if (forceAsyncEvents[eventName] && $rootScope.$$phase) { | |||
scope.$evalAsync(callback); | |||
} else if ($rootScope.$$phase) { |
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.
In order to avoid double checking $rootScope.$$phase
and simplify, I might change the whole block to:
if (!$rootScope.$$phase) {
scope.$apply(callback);
} else if (forceAsyncEvents[eventName]) {
scope.$evalAsync(callback);
} else {
callback();
}
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.
Great point, I've updated the commit to reflect this.
Technically speaking, there are ways to avoid this (e.g. wrapping the call to But then again, why not ? It has minimal overhead and is a reasonable change 👍 LGTM |
@gkalpak very true, I have had this happen a couple of times and normally worked around it. |
I think the reason this was never done is because it makes |
@jbedard that makes sense that would be a concern. Though I don't think this change will effect that. The biggest difference is whether it will use $rootScope.$apply or a regular function call to call the event handler. Both should be synchronous if I understand the code correctly. |
My bad then! I guess it's only the |
Previously if an non-async ng-event was fired while a So, the only change in terms of behavior is that calls that would previously throw, now won't. Moving the expectation inside the I would be fine adding adding another test that verifies the synchronous nature of both types of callback calls (events fired inside and outside of |
I've updated the PR to include another test to cover triggering an event outside of a digest cycle. |
element.triggerHandler('click'); | ||
}); | ||
|
||
expect($rootScope.click).toHaveBeenCalledOnce(); |
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 actually check that it is called synchronously (e.g. it might be called outside of the $apply()
block).
You could use the same approach as below (using a $watch
).
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.
I've updated the PR to use the same checks for both tests
…on't $apply if already in $digest Digest cycle already in progress error can inadvertently be caused when triggering an element's click event while within an active digest cycle. This is due to the ngEventsDirs event handler always calling $rootScope.$apply regardless of the status of $rootScope.$$phase. Checking the phase and calling the function immediately if within an active digest cycle will prevent the problem without reducing current functionality. Closes #14673
…on't $apply if already in $digest Digest cycle already in progress error can inadvertently be caused when triggering an element's click event while within an active digest cycle. This is due to the ngEventsDirs event handler always calling $rootScope.$apply regardless of the status of $rootScope.$$phase. Checking the phase and calling the function immediately if within an active digest cycle will prevent the problem without reducing current functionality. Closes angular#14673 Closes angular#14674
…on't $apply if already in $digest Digest cycle already in progress error can inadvertently be caused when triggering an element's click event while within an active digest cycle. This is due to the ngEventsDirs event handler always calling $rootScope.$apply regardless of the status of $rootScope.$$phase. Checking the phase and calling the function immediately if within an active digest cycle will prevent the problem without reducing current functionality. Closes angular#14673 Closes angular#14674
…n $digest Digest cycle already in progress error can inadvertently be caused when triggering an element's click event while within an active digest cycle. This is due to the ngEventsDirs event handler always calling $rootScope.$apply regardless of the status of $rootScope.$$phase. Checking the phase and calling the function immediately if within an active digest cycle will prevent the problem without reducing current functionality. Closes angular#14673 Closes angular#14674
…n $digest Digest cycle already in progress error can inadvertently be caused when triggering an element's click event while within an active digest cycle. This is due to the ngEventsDirs event handler always calling $rootScope.$apply regardless of the status of $rootScope.$$phase. Checking the phase and calling the function immediately if within an active digest cycle will prevent the problem without reducing current functionality. Closes angular#14673 Closes angular#14674
…n $digest Digest cycle already in progress error can inadvertently be caused when triggering an element's click event while within an active digest cycle. This is due to the ngEventsDirs event handler always calling $rootScope.$apply regardless of the status of $rootScope.$$phase. Checking the phase and calling the function immediately if within an active digest cycle will prevent the problem without reducing current functionality. Closes #14673 Closes #14674
What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Bug fix
What is the current behavior? (You can also link to an open issue here)
#14673
Digest cycle already in progress error can inadvertently be caused when triggering an$rootScope.$ $phase.
element's click event while within an active digest cycle. This is due to the ngEventsDirs
event handler always calling $rootScope.$apply regardless of the status of
Checking the phase and calling the function immediately if within an active digest cycle
will prevent the problem without reducing current functionality.
What is the new behavior (if this is a feature change)?$rootScope.$ $phase to determine if it should call the callback function without entering a new $apply.
This will change ngClick and the like to check for
Does this PR introduce a breaking change?
Nope
Please check if the PR fulfills these requirements
Other information: