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

Commit f81ff3b

Browse files
fix($browser): prevent infinite digest if changing hash when there is no hashPrefix
The `window.location.hash' setter will strip of a single leading hash character if it exists from the fragment before joining the fragment value to the href with a new hash character. This meant that if we want the fragment to lead with a hash character, we must do `window.location.hash = '##test'` to ensure that the first hash character in the fragment is not lost. The `$location.hash` setter works differently and assumes that the value passed is the the full fragment, i.e. it does not attempt to strip off a single leading hash character. Previously, if you called, `$location.hash('#test')`, the leading hash was being stripped and the resulting url fragment did not contain this hash: `$location.hash()`, then became 'test' rather than `#test`, which led to an infinite digest. Closes #10423 Closes #12145
1 parent 720012e commit f81ff3b

File tree

3 files changed

+19
-8
lines changed

3 files changed

+19
-8
lines changed

src/ng/browser.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function Browser(window, document, $log, $sniffer) {
6363

6464
function getHash(url) {
6565
var index = url.indexOf('#');
66-
return index === -1 ? '' : url.substr(index + 1);
66+
return index === -1 ? '' : url.substr(index);
6767
}
6868

6969
/**

test/ng/browserSpecs.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ function MockWindow(options) {
5757
return getHash(locationHref);
5858
},
5959
set hash(value) {
60-
locationHref = stripHash(locationHref) + '#' + value;
60+
// replace the hash with the new one (stripping off a leading hash if there is one)
61+
// See hash setter spec: https://url.spec.whatwg.org/#urlutils-and-urlutilsreadonly-members
62+
locationHref = stripHash(locationHref) + '#' + value.replace(/^#/,'');
6163
},
6264
replace: function(url) {
6365
locationHref = url;

test/ng/locationSpec.js

+15-6
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,18 @@ describe('$location', function() {
989989
expect($browser.url()).toBe('http://new.com/a/b#!/changed');
990990
});
991991
});
992+
993+
994+
it('should not infinitely digest if hash is set when there is no hashPrefix', function() {
995+
initService({html5Mode:false, hashPrefix:'', supportHistory:true});
996+
mockUpBrowser({initialUrl:'http://new.com/a/b', baseHref:'/a/b'});
997+
inject(function($rootScope, $browser, $location) {
998+
$location.hash('test');
999+
1000+
$rootScope.$digest();
1001+
expect($browser.url()).toBe('http://new.com/a/b##test');
1002+
});
1003+
});
9921004
});
9931005

9941006
describe('wiring in html5 mode', function() {
@@ -2507,17 +2519,11 @@ describe('$location', function() {
25072519
win.history = {
25082520
state: options.state || null,
25092521
replaceState: function(state, title, url) {
2510-
// console.log('REPLACESTATE');
2511-
// console.log('CURRENT', win.location.href, win.history.state);
2512-
// console.log('NEW', url, state);
25132522
win.history.state = copy(state);
25142523
if (url) win.location.href = url;
25152524
jqLite(win).triggerHandler('popstate');
25162525
},
25172526
pushState: function(state, title, url) {
2518-
// console.log('PUSHSTATE');
2519-
// console.log('CURRENT', win.location.href, win.history.state);
2520-
// console.log('NEW', url, state);
25212527
win.history.state = copy(state);
25222528
if (url) win.location.href = url;
25232529
jqLite(win).triggerHandler('popstate');
@@ -2529,6 +2535,9 @@ describe('$location', function() {
25292535
get href() { return parser.href; },
25302536
set href(val) { parser.href = val; },
25312537
get hash() { return parser.hash; },
2538+
// The parser correctly strips on a single preceding hash character if necessary
2539+
// before joining the fragment onto the href by a new hash character
2540+
// See hash setter spec: https://url.spec.whatwg.org/#urlutils-and-urlutilsreadonly-members
25322541
set hash(val) { parser.hash = val; },
25332542

25342543
replace: function(val) {

0 commit comments

Comments
 (0)