Skip to content

Commit

Permalink
[fixed] URL hash consistency across browsers
Browse files Browse the repository at this point in the history
Unlike other browsers, Firefox will pre-decode the value retrieved
from window.location.hash.  This causes the parameters passed down
to React components from the router to potentially be different in
Firefox vs. other browsers.  Additionally, hashes containing the
string '%25' can cause react-router to throw exceptions, since
this value will be decoded to '%' by Firefox, and then passed by
react-router to the `decodeURI` function, which will consider it
invalid unless it is followed by two more hex digits.

In order to fix these problems, reads of window.location.hash have
been replaced with window.location.href.split('#')[1], which
is consistently the un-decoded string in all browsers.
  • Loading branch information
rpokorny committed Dec 2, 2014
1 parent 61fe033 commit a07003e
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
6 changes: 4 additions & 2 deletions modules/locations/HashLocation.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var LocationActions = require('../actions/LocationActions');
var Path = require('../utils/Path');

/**
* Returns the current URL path from `window.location.hash`, including query string
* Returns the current URL path from the `hash` section of the URL, including query string
*/
function getHashPath() {
invariant(
Expand All @@ -13,7 +13,9 @@ function getHashPath() {
);

return Path.decode(
window.location.hash.substr(1)
//cannot use window.location.hash because its not consistent
//across browsers - Firefox will pre-decode it
window.location.href.split('#')[1] || ''
);
}

Expand Down
45 changes: 45 additions & 0 deletions modules/locations/__tests__/HashLocation-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
var expect = require('expect');
var HashLocation = require('../HashLocation');

describe('HashLocation.getCurrentPath', function() {

//this test is needed because Firefox will pre-decode the value retrieved from
//window.location.hash
it('returns a properly decoded equivalent of what window.location.hash is set to', function() {
window.location.hash = '';
expect(HashLocation.getCurrentPath()).toBe('');

window.location.hash = 'asdf';
expect(HashLocation.getCurrentPath()).toBe('asdf');

window.location.hash = 'test+spaces';
expect(HashLocation.getCurrentPath()).toBe('test spaces');

window.location.hash = 'first%2Fsecond';
expect(HashLocation.getCurrentPath()).toBe('first%2Fsecond');

window.location.hash = 'first/second';
expect(HashLocation.getCurrentPath()).toBe('first/second');

window.location.hash = 'first%252Fsecond';
expect(HashLocation.getCurrentPath()).toBe('first%2Fsecond');

//decodeURI doesn't handle lone percents
window.location.hash = '%';
expect(function() {
HashLocation.getCurrentPath();
}).toThrow(URIError);

window.location.hash = '%25';
expect(HashLocation.getCurrentPath()).toBe('%');

window.location.hash =
'complicated+string/full%2Fof%3Fspecial%25chars%2520and%23escapes%E1%88%B4';
expect(HashLocation.getCurrentPath())
.toBe('complicated string/full%2Fof%3Fspecial%chars%20and%23escapesሴ');
});

afterEach(function() {
window.location.hash = '';
});
});

0 comments on commit a07003e

Please sign in to comment.