aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVojta Jina2012-01-13 16:38:08 -0800
committerVojta Jina2012-01-14 11:23:12 -0800
commitc49b8a2db5d916a9213547125af996d6c853230c (patch)
treed8e4d639306790d2466ba01b15410342db4c2d7c
parent5cdfe45aa3e50fabad44009c1b8511253c6e4915 (diff)
downloadangular.js-c49b8a2db5d916a9213547125af996d6c853230c.tar.bz2
fix($location): do not $digest if browser's url change fired within $apply/$digest
Chrome (probably other browsers as well) fires 'hashchange' event synchronously, so if you change raw location from within $apply/$digest, we don't want to $apply twice. (It would throw an exception)
-rw-r--r--src/service/location.js6
-rw-r--r--test/service/locationSpec.js37
2 files changed, 41 insertions, 2 deletions
diff --git a/src/service/location.js b/src/service/location.js
index d0ae9de7..3e8ba0c3 100644
--- a/src/service/location.js
+++ b/src/service/location.js
@@ -530,8 +530,10 @@ function $LocationProvider(){
// update $location when $browser url changes
$browser.onUrlChange(function(newUrl) {
if (currentUrl.absUrl() != newUrl) {
- currentUrl.$$parse(newUrl);
- $rootScope.$apply();
+ $rootScope.$evalAsync(function() {
+ currentUrl.$$parse(newUrl);
+ });
+ if (!$rootScope.$$phase) $rootScope.$digest();
}
});
diff --git a/test/service/locationSpec.js b/test/service/locationSpec.js
index c7cc9c23..97f2ab63 100644
--- a/test/service/locationSpec.js
+++ b/test/service/locationSpec.js
@@ -364,6 +364,43 @@ describe('$location', function() {
}));
+ // location.href = '...' fires hashchange event synchronously, so it might happen inside $apply
+ it('should not $apply when browser url changed inside $apply', inject(
+ function($rootScope, $browser, $location) {
+ var OLD_URL = $browser.url(),
+ NEW_URL = 'http://updated.com/url';
+
+
+ $rootScope.$apply(function() {
+ $browser.url(NEW_URL);
+ $browser.poll(); // simulate firing event from browser
+ expect($location.absUrl()).toBe(OLD_URL); // should be async
+ });
+
+ expect($location.absUrl()).toBe(NEW_URL);
+ }));
+
+ // location.href = '...' fires hashchange event synchronously, so it might happen inside $digest
+ it('should not $apply when browser url changed inside $digest', inject(
+ function($rootScope, $browser, $location) {
+ var OLD_URL = $browser.url(),
+ NEW_URL = 'http://updated.com/url',
+ notRunYet = true;
+
+ $rootScope.$watch(function() {
+ if (notRunYet) {
+ notRunYet = false;
+ $browser.url(NEW_URL);
+ $browser.poll(); // simulate firing event from browser
+ expect($location.absUrl()).toBe(OLD_URL); // should be async
+ }
+ });
+
+ $rootScope.$digest();
+ expect($location.absUrl()).toBe(NEW_URL);
+ }));
+
+
it('should update browser when $location changes', inject(function($rootScope, $browser, $location) {
var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
$location.path('/new/path');