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

$location causes infinite digest #12571

Closed
yeerkkiller1 opened this issue Aug 13, 2015 · 0 comments
Closed

$location causes infinite digest #12571

yeerkkiller1 opened this issue Aug 13, 2015 · 0 comments

Comments

@yeerkkiller1
Copy link

Steps to reproduce:

  1. Use ng-include
  2. Run window.history.pushState('', '', '?/'); inside the link function of a directive
  3. Use that directive inside an ng-repeat
  4. Set $locationProvider to use html5 mode

The issue can be seen in a fairly simple form here: http://jsbin.com/kapedo/edit?html,console

This is a massive issue, I am not trying to use $location at all. I only set it to html5 mode so it doesn't change my url.

This has the same consequence as #1417, but the source is probably different. $location seems to have a lot of bugs related to its storing of the url and assuming no one else is going to change it. Using $location is not an option, window.history.pushState is being called by a library I have no control over.

At the very least an opt-out for $location should exist, as it is already in AngularJS and any bugs in it are going to mess up the url, even for people who are not using $location.

@yeerkkiller1 yeerkkiller1 changed the title $location causes into infinite digest $location causes infinite digest Aug 13, 2015
@Narretz Narretz added this to the Backlog milestone Dec 2, 2015
gkalpak added a commit to gkalpak/angular.js that referenced this issue Jan 4, 2017
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
gkalpak added a commit to gkalpak/angular.js that referenced this issue Jan 4, 2017
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
@gkalpak gkalpak closed this as completed in 752f411 Jan 9, 2017
gkalpak added a commit that referenced this issue Jan 9, 2017
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
ellimist pushed a commit to ellimist/angular.js that referenced this issue Mar 15, 2017
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
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants