Skip to content

Commit f44558b

Browse files
committed
fix($browser, $location): prevent url() from triggering onUrlChange()
On Android 2.2 and 2.3, infinite digest loops are occasionally triggered by changing $location.path() The problem is caused by a faulty assumption in $browser.onUrlChange(). The assumption is that the hashchange event will only fire as a result of non-Angular actions, e.g. a human editing the browser's url. Unfortunately in Android 2.2 and 2.3, this occasionally fires when browser.url() changes the url. The knock-on effect is a race condition between $location's two monitoring loops: one watches for manual browser url changes using $browser.onUrlChange and updates $location's inner data, while the other ($locationWatch) watches for changes in $location.absUrl() and synchs them to $browser. They end up reversing each other's changes in a vicious cycle until Angular cuts them off.
1 parent e4415d2 commit f44558b

File tree

1 file changed

+6
-2
lines changed

1 file changed

+6
-2
lines changed

src/ng/browser.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ function Browser(window, document, $log, $sniffer) {
125125

126126
var lastBrowserUrl = location.href,
127127
baseElement = document.find('base'),
128-
replacedUrl = null;
128+
replacedUrl = null,
129+
ignoreHashChange = false;
129130

130131
/**
131132
* @name ng.$browser#url
@@ -160,13 +161,16 @@ function Browser(window, document, $log, $sniffer) {
160161
baseElement.attr('href', baseElement.attr('href'));
161162
}
162163
} else {
164+
// Flag to ignore hashchange events occasionally generated in Android 2.2, 2.3
165+
ignoreHashChange = true;
163166
if (replace) {
164167
location.replace(url);
165168
replacedUrl = url;
166169
} else {
167170
location.href = url;
168171
replacedUrl = null;
169172
}
173+
ignoreHashChange = false;
170174
}
171175
return self;
172176
// getter
@@ -182,7 +186,7 @@ function Browser(window, document, $log, $sniffer) {
182186
urlChangeInit = false;
183187

184188
function fireUrlChange() {
185-
if (lastBrowserUrl == self.url()) return;
189+
if (lastBrowserUrl == self.url() || ignoreHashChange) return;
186190

187191
lastBrowserUrl = self.url();
188192
forEach(urlChangeListeners, function(listener) {

0 commit comments

Comments
 (0)