mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-01-13 17:02:23 +08:00
fix($browser): prevent infinite digests when clearing the hash of a url
By using `location.hash` to update the current browser location when only the hash has changed, we prevent the browser from attempting to reload. Closes #9629 Closes #9635 Closes #10228 Closes #10308
This commit is contained in:
committed by
Jeff Cross
parent
5f52957503
commit
9845cee63e
@@ -62,6 +62,11 @@ function Browser(window, document, $log, $sniffer) {
|
||||
}
|
||||
}
|
||||
|
||||
function getHash(url) {
|
||||
var index = url.indexOf('#');
|
||||
return index === -1 ? '' : url.substr(index + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Note: this method is used only by scenario runner
|
||||
@@ -173,8 +178,10 @@ function Browser(window, document, $log, $sniffer) {
|
||||
}
|
||||
if (replace) {
|
||||
location.replace(url);
|
||||
} else {
|
||||
} else if (!sameBase) {
|
||||
location.href = url;
|
||||
} else {
|
||||
location.hash = getHash(url);
|
||||
}
|
||||
}
|
||||
return self;
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
function MockWindow() {
|
||||
/* global getHash:true, stripHash:true */
|
||||
|
||||
var historyEntriesLength;
|
||||
var sniffer = {};
|
||||
|
||||
function MockWindow(options) {
|
||||
if (typeof options !== 'object') {
|
||||
options = {};
|
||||
}
|
||||
var events = {};
|
||||
var timeouts = this.timeouts = [];
|
||||
var locationHref = 'http://server/';
|
||||
var mockWindow = this;
|
||||
|
||||
this.setTimeout = function(fn) {
|
||||
return timeouts.push(fn) - 1;
|
||||
@@ -36,8 +46,24 @@ function MockWindow() {
|
||||
};
|
||||
|
||||
this.location = {
|
||||
href: 'http://server/',
|
||||
replace: noop
|
||||
get href() {
|
||||
return locationHref;
|
||||
},
|
||||
set href(value) {
|
||||
locationHref = value;
|
||||
mockWindow.history.state = null;
|
||||
historyEntriesLength++;
|
||||
},
|
||||
get hash() {
|
||||
return getHash(locationHref);
|
||||
},
|
||||
set hash(value) {
|
||||
locationHref = stripHash(locationHref) + '#' + value;
|
||||
},
|
||||
replace: function(url) {
|
||||
locationHref = url;
|
||||
mockWindow.history.state = null;
|
||||
}
|
||||
};
|
||||
|
||||
this.history = {
|
||||
@@ -451,6 +477,17 @@ describe('browser', function() {
|
||||
expect(locationReplace).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should retain the # character when the only change is clearing the hash fragment, to prevent page reload", function() {
|
||||
sniffer.history = true;
|
||||
|
||||
browser.url('http://server/#123');
|
||||
expect(fakeWindow.location.href).toEqual('http://server/#123');
|
||||
|
||||
browser.url('http://server/');
|
||||
expect(fakeWindow.location.href).toEqual('http://server/#');
|
||||
|
||||
});
|
||||
|
||||
it('should use location.replace when history.replaceState not available', function() {
|
||||
sniffer.history = false;
|
||||
browser.url('http://new.org', true);
|
||||
@@ -462,6 +499,7 @@ describe('browser', function() {
|
||||
expect(fakeWindow.location.href).toEqual('http://server/');
|
||||
});
|
||||
|
||||
|
||||
it('should use location.replace and not use replaceState when the url only changed in the hash fragment to please IE10/11', function() {
|
||||
sniffer.history = true;
|
||||
browser.url('http://server/#123', true);
|
||||
@@ -473,6 +511,7 @@ describe('browser', function() {
|
||||
expect(fakeWindow.location.href).toEqual('http://server/');
|
||||
});
|
||||
|
||||
|
||||
it('should return $browser to allow chaining', function() {
|
||||
expect(browser.url('http://any.com')).toBe(browser);
|
||||
});
|
||||
@@ -835,7 +874,6 @@ describe('browser', function() {
|
||||
expect(browser.url()).toBe(newUrl);
|
||||
$rootScope.$digest();
|
||||
expect(browser.url()).toBe(newUrl);
|
||||
expect(fakeWindow.location.href).toBe(current);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user