-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Internet Explorer infinite digest with location change #15556
Comments
Actually, this has nothing to do with the |
@thetrevdev Do you have a workaround for this? It looks like it's difficult to fix at this point. |
…e` event Affects IE11. Fixes angular#15556
…e` event Affects IE11. Fixes angular#15556
This sounds reasonable. Based on that, I have a potential fix here. (I still need to add tests, but it didn't break any of the existing tests, which is a good sign 😃) |
Previously, when the URL was changed directly (e.g. via `location.href`) during a `$digest` (e.g. via `scope.$evalAsync()` or `promise.then()`) the change was not handled correctly, unless a `popstate` or `hashchange` event was fired synchronously. This wasn't an issue in most browsers, where the `popstate` event was fired synchronously. In IE11 though, the `popstate` event is not fired at all for hash-only changes ([known bug][1]) and the `hashchange` event is fired asynchronously (which is too late). This commit fixes it by keeping track of `$location` setter methods being called and only processing a URL change if it originated from such a call. If there is a URL difference but no setter method has been called, this means that the browser URL has been updated directly and the change hasn't yet been propagated to `$location` (e.g. due to no synchronous `popstate` event). In that case, the change will be propagated subsequently by the (asynchronous) `hashchange` event. [1]: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/3740423/ Fixes angular#15556
Previously, when the URL was changed directly (e.g. via `location.href`) during a `$digest` (e.g. via `scope.$evalAsync()` or `promise.then()`) the change was not handled correctly, unless a `popstate` or `hashchange` event was fired synchronously. This wasn't an issue in most browsers, where the `popstate` event was fired synchronously. In IE11 though, the `popstate` event is not fired at all for hash-only changes ([known bug][1]) and the `hashchange` event is fired asynchronously (which is too late). This commit fixes it by keeping track of `$location` setter methods being called and only processing a URL change if it originated from such a call. If there is a URL difference but no setter method has been called, this means that the browser URL has been updated directly and the change hasn't yet been propagated to `$location` (e.g. due to no synchronous `popstate` event). In that case, the change will be propagated later by the (asynchronous) `hashchange` event. [1]: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/3740423/ Fixes angular#15556
There you go: #15561 |
Tested it in our app. Looks good in our tests. Thanks! |
Previously, when the URL was changed directly (e.g. via `location.href`) during a `$digest` (e.g. via `scope.$evalAsync()` or `promise.then()`) the change was not handled correctly, unless a `popstate` or `hashchange` event was fired synchronously. This was an issue when calling `history.pushState()/replaceState()` in all browsers, since these methods do not emit any event. This was also an issue in IE11, where (unlike other browsers) no `popstate` event is fired at all for hash-only changes ([known bug][1]) and the `hashchange` event is fired asynchronously (which is too late). This commit fixes both usecases by: 1. Keeping track of `$location` setter methods being called and only processing a URL change if it originated from such a call. If there is a URL difference but no setter method has been called, this means that the browser URL/history has been updated directly and the change hasn't yet been propagated to `$location` (e.g. due to no event being fired synchronously or at all). 2. Checking for URL/state changes at the end of the `$digest`, in order to detect changes via `history` methods (that took place during the `$digest`). [1]: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/3740423/ Fixes angular#11075 Fixes angular#12571 Fixes angular#15556
Previously, when the URL was changed directly (e.g. via `location.href`) during a `$digest` (e.g. via `scope.$evalAsync()` or `promise.then()`) the change was not handled correctly, unless a `popstate` or `hashchange` event was fired synchronously. This was an issue when calling `history.pushState()/replaceState()` in all browsers, since these methods do not emit any event. This was also an issue when setting `location.href` in IE11, where (unlike other browsers) no `popstate` event is fired at all for hash-only changes ([known bug][1]) and the `hashchange` event is fired asynchronously (which is too late). This commit fixes both usecases by: 1. Keeping track of `$location` setter methods being called and only processing a URL change if it originated from such a call. If there is a URL difference but no setter method has been called, this means that the browser URL/history has been updated directly and the change hasn't yet been propagated to `$location` (e.g. due to no event being fired synchronously or at all). 2. Checking for URL/state changes at the end of the `$digest`, in order to detect changes via `history` methods (that took place during the `$digest`). [1]: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/3740423/ Fixes angular#11075 Fixes angular#12571 Fixes angular#15556
Previously, when the URL was changed directly (e.g. via `location.href`) during a `$digest` (e.g. via `scope.$evalAsync()` or `promise.then()`) the change was not handled correctly, unless a `popstate` or `hashchange` event was fired synchronously. This was an issue when calling `history.pushState()/replaceState()` in all browsers, since these methods do not emit any event. This was also an issue when setting `location.href` in IE11, where (unlike other browsers) no `popstate` event is fired at all for hash-only changes ([known bug][1]) and the `hashchange` event is fired asynchronously (which is too late). This commit fixes both usecases by: 1. Keeping track of `$location` setter methods being called and only processing a URL change if it originated from such a call. If there is a URL difference but no setter method has been called, this means that the browser URL/history has been updated directly and the change hasn't yet been propagated to `$location` (e.g. due to no event being fired synchronously or at all). 2. Checking for URL/state changes at the end of the `$digest`, in order to detect changes via `history` methods (that took place during the `$digest`). [1]: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/3740423/ Fixes #11075 Fixes #12571 Fixes #15556 Closes #15561
Previously, when the URL was changed directly (e.g. via `location.href`) during a `$digest` (e.g. via `scope.$evalAsync()` or `promise.then()`) the change was not handled correctly, unless a `popstate` or `hashchange` event was fired synchronously. This was an issue when calling `history.pushState()/replaceState()` in all browsers, since these methods do not emit any event. This was also an issue when setting `location.href` in IE11, where (unlike other browsers) no `popstate` event is fired at all for hash-only changes ([known bug][1]) and the `hashchange` event is fired asynchronously (which is too late). This commit fixes both usecases by: 1. Keeping track of `$location` setter methods being called and only processing a URL change if it originated from such a call. If there is a URL difference but no setter method has been called, this means that the browser URL/history has been updated directly and the change hasn't yet been propagated to `$location` (e.g. due to no event being fired synchronously or at all). 2. Checking for URL/state changes at the end of the `$digest`, in order to detect changes via `history` methods (that took place during the `$digest`). [1]: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/3740423/ Fixes angular#11075 Fixes angular#12571 Fixes angular#15556 Closes angular#15561
Bug
Current behavior
http://plnkr.co/edit/7SldRRsrYFO32hiG9abV?p=preview
Infinite digest error in Internet Explorer console after button click
[$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
Expected behavior
Location changes without error
Minimal reproduction of the problem with instructions
http://plnkr.co/edit/7SldRRsrYFO32hiG9abV?p=preview with Internet Explorer
Check error console after button click.
Note: this happens when the location change occurs during an $evalAsync
What is the motivation / use case for changing the behavior?
We have a large app with different redirect scenarios that may or may not be local to our app. We wish to set location.href.
Angular version: 1.5/1.6
Browser: [ IE 11 ]
In internet explorer the hashchange event fires asynchronously. this causes the $locationWatch to think that the $location url was updated as it doesn't match $browser url. It seems like the location logic should know whether a url change occured via $location setters
**Relevant Code:
https://github.com/angular/angular.js/blob/master/src/ng/location.js#L970
The text was updated successfully, but these errors were encountered: