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

Commit f486ebe

Browse files
fix($location): do not get caught in infinite digest in IE9
Thanks to @hamfastgamgee for getting this fix in place. Closes #11439 Closes #11675 Closes #11935 Closes #12083
1 parent 03190fd commit f486ebe

File tree

2 files changed

+172
-1
lines changed

2 files changed

+172
-1
lines changed

src/ng/browser.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ function Browser(window, document, $log, $sniffer) {
190190
// Do the assignment again so that those two variables are referentially identical.
191191
lastHistoryState = cachedState;
192192
} else {
193-
if (!sameBase) {
193+
if (!sameBase || reloadLocation) {
194194
reloadLocation = url;
195195
}
196196
if (replace) {

test/ng/locationSpec.js

+171
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,27 @@ describe('$location', function() {
663663
});
664664
});
665665

666+
667+
it('should not get caught in infinite digest when replacing path in locationChangeSuccess handler', function() {
668+
initService({html5Mode:true,supportHistory:false});
669+
mockUpBrowser({initialUrl:'http://server/base/home', baseHref:'/base/'});
670+
inject(
671+
function($browser, $location, $rootScope, $window) {
672+
var handlerCalled = false;
673+
$rootScope.$on('$locationChangeSuccess', function() {
674+
handlerCalled = true;
675+
if ($location.path() !== '/') {
676+
$location.path('/').replace();
677+
}
678+
});
679+
expect($browser.url()).toEqual('http://server/base/#/home');
680+
$rootScope.$digest();
681+
expect(handlerCalled).toEqual(true);
682+
expect($browser.url()).toEqual('http://server/base/#/');
683+
}
684+
);
685+
});
686+
666687
it('should not infinitely digest when using a semicolon in initial path', function() {
667688
initService({html5Mode:true,supportHistory:true});
668689
mockUpBrowser({initialUrl:'http://localhost:9876/;jsessionid=foo', baseHref:'/'});
@@ -672,6 +693,156 @@ describe('$location', function() {
672693
}).not.toThrow();
673694
});
674695
});
696+
697+
698+
function updatePathOnLocationChangeSuccessTo(newPath) {
699+
inject(function($rootScope, $location) {
700+
$rootScope.$on('$locationChangeSuccess', function(event, newUrl, oldUrl) {
701+
$location.path(newPath);
702+
});
703+
});
704+
}
705+
706+
707+
describe('location watch for hashbang browsers', function() {
708+
709+
it('should not infinite $digest when going to base URL without trailing slash when $locationChangeSuccess watcher changes path to /Home', function() {
710+
initService({html5Mode: true, supportHistory: false});
711+
mockUpBrowser({initialUrl:'http://server/app/', baseHref:'/app/'});
712+
inject(function($rootScope, $location, $browser) {
713+
var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
714+
715+
updatePathOnLocationChangeSuccessTo('/Home');
716+
717+
$rootScope.$digest();
718+
719+
expect($browser.url()).toEqual('http://server/app/#/Home');
720+
expect($location.path()).toEqual('/Home');
721+
expect($browserUrl.calls.length).toEqual(1);
722+
});
723+
});
724+
725+
it('should not infinite $digest when going to base URL without trailing slash when $locationChangeSuccess watcher changes path to /', function() {
726+
initService({html5Mode: true, supportHistory: false});
727+
mockUpBrowser({initialUrl:'http://server/app/Home', baseHref:'/app/'});
728+
inject(function($rootScope, $location, $browser, $window) {
729+
var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
730+
731+
updatePathOnLocationChangeSuccessTo('/');
732+
733+
$rootScope.$digest();
734+
735+
expect($browser.url()).toEqual('http://server/app/#/');
736+
expect($location.path()).toEqual('/');
737+
expect($browserUrl.calls.length).toEqual(1);
738+
expect($browserUrl.calls[0].args).toEqual(['http://server/app/#/', false, null]);
739+
});
740+
});
741+
742+
it('should not infinite $digest when going to base URL with trailing slash when $locationChangeSuccess watcher changes path to /Home', function() {
743+
initService({html5Mode: true, supportHistory: false});
744+
mockUpBrowser({initialUrl:'http://server/app/', baseHref:'/app/'});
745+
inject(function($rootScope, $location, $browser) {
746+
var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
747+
748+
updatePathOnLocationChangeSuccessTo('/Home');
749+
$rootScope.$digest();
750+
751+
expect($browser.url()).toEqual('http://server/app/#/Home');
752+
expect($location.path()).toEqual('/Home');
753+
expect($browserUrl.calls.length).toEqual(1);
754+
expect($browserUrl.calls[0].args).toEqual(['http://server/app/#/Home', false, null]);
755+
});
756+
});
757+
758+
it('should not infinite $digest when going to base URL with trailing slash when $locationChangeSuccess watcher changes path to /', function() {
759+
initService({html5Mode: true, supportHistory: false});
760+
mockUpBrowser({initialUrl:'http://server/app/', baseHref:'/app/'});
761+
inject(function($rootScope, $location, $browser) {
762+
var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
763+
764+
updatePathOnLocationChangeSuccessTo('/');
765+
$rootScope.$digest();
766+
767+
expect($browser.url()).toEqual('http://server/app/#/');
768+
expect($location.path()).toEqual('/');
769+
expect($browserUrl.calls.length).toEqual(1);
770+
});
771+
});
772+
});
773+
774+
775+
describe('location watch for HTML5 browsers', function() {
776+
777+
it('should not infinite $digest when going to base URL without trailing slash when $locationChangeSuccess watcher changes path to /Home', function() {
778+
initService({html5Mode: true, supportHistory: true});
779+
mockUpBrowser({initialUrl:'http://server/app/', baseHref:'/app/'});
780+
inject(function($rootScope, $injector, $browser) {
781+
var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
782+
783+
var $location = $injector.get('$location');
784+
updatePathOnLocationChangeSuccessTo('/Home');
785+
786+
$rootScope.$digest();
787+
788+
expect($browser.url()).toEqual('http://server/app/Home');
789+
expect($location.path()).toEqual('/Home');
790+
expect($browserUrl.calls.length).toEqual(1);
791+
});
792+
});
793+
794+
it('should not infinite $digest when going to base URL without trailing slash when $locationChangeSuccess watcher changes path to /', function() {
795+
initService({html5Mode: true, supportHistory: true});
796+
mockUpBrowser({initialUrl:'http://server/app/', baseHref:'/app/'});
797+
inject(function($rootScope, $injector, $browser) {
798+
var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
799+
800+
var $location = $injector.get('$location');
801+
updatePathOnLocationChangeSuccessTo('/');
802+
803+
$rootScope.$digest();
804+
805+
expect($browser.url()).toEqual('http://server/app/');
806+
expect($location.path()).toEqual('/');
807+
expect($browserUrl.calls.length).toEqual(0);
808+
});
809+
});
810+
811+
it('should not infinite $digest when going to base URL with trailing slash when $locationChangeSuccess watcher changes path to /Home', function() {
812+
initService({html5Mode: true, supportHistory: true});
813+
mockUpBrowser({initialUrl:'http://server/app/', baseHref:'/app/'});
814+
inject(function($rootScope, $injector, $browser) {
815+
var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
816+
817+
var $location = $injector.get('$location');
818+
updatePathOnLocationChangeSuccessTo('/Home');
819+
820+
$rootScope.$digest();
821+
822+
expect($browser.url()).toEqual('http://server/app/Home');
823+
expect($location.path()).toEqual('/Home');
824+
expect($browserUrl.calls.length).toEqual(1);
825+
});
826+
});
827+
828+
it('should not infinite $digest when going to base URL with trailing slash when $locationChangeSuccess watcher changes path to /', function() {
829+
initService({html5Mode: true, supportHistory: true});
830+
mockUpBrowser({initialUrl:'http://server/app/', baseHref:'/app/'});
831+
inject(function($rootScope, $injector, $browser) {
832+
var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').andCallThrough();
833+
834+
var $location = $injector.get('$location');
835+
updatePathOnLocationChangeSuccessTo('/');
836+
837+
$rootScope.$digest();
838+
839+
expect($browser.url()).toEqual('http://server/app/');
840+
expect($location.path()).toEqual('/');
841+
expect($browserUrl.calls.length).toEqual(0);
842+
});
843+
});
844+
});
845+
675846
});
676847

677848
describe('wiring', function() {

0 commit comments

Comments
 (0)