From 7b8ab30f98855c31e74eb72f2592a8fff9d7d3ac Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Wed, 11 Sep 2019 13:13:56 -0700 Subject: [PATCH] Undo changes from 78f016 and 0fe9cb This is a temporary change so we can get the master branch back into a state to cut 4.x releases. --- modules/LocationUtils.js | 15 +++++++++++++++ modules/__tests__/BrowserHistory-test.js | 12 ++++++++++++ modules/__tests__/HashHistory-test.js | 12 ++++++++++++ modules/__tests__/MemoryHistory-test.js | 12 ++++++++++++ .../TestSequences/LocationPathnameAlwaysSame.js | 5 ++--- .../TestSequences/PushEncodedLocation.js | 4 ++-- .../TestSequences/PushInvalidPathname.js | 17 +++++++++++++++++ .../TestSequences/ReplaceInvalidPathname.js | 17 +++++++++++++++++ modules/__tests__/TestSequences/index.js | 2 ++ 9 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 modules/__tests__/TestSequences/PushInvalidPathname.js create mode 100644 modules/__tests__/TestSequences/ReplaceInvalidPathname.js diff --git a/modules/LocationUtils.js b/modules/LocationUtils.js index 36e5699b7..27cb0f88d 100644 --- a/modules/LocationUtils.js +++ b/modules/LocationUtils.js @@ -32,6 +32,21 @@ export function createLocation(path, state, key, currentLocation) { location.state = state; } + try { + location.pathname = decodeURI(location.pathname); + } catch (e) { + if (e instanceof URIError) { + throw new URIError( + 'Pathname "' + + location.pathname + + '" could not be decoded. ' + + 'This is likely caused by an invalid percent-encoding.' + ); + } else { + throw e; + } + } + if (key) location.key = key; if (currentLocation) { diff --git a/modules/__tests__/BrowserHistory-test.js b/modules/__tests__/BrowserHistory-test.js index 0da47710e..a9ac32d66 100644 --- a/modules/__tests__/BrowserHistory-test.js +++ b/modules/__tests__/BrowserHistory-test.js @@ -78,6 +78,12 @@ describe('a browser history', () => { }); }); + describe('push with an invalid pathname (bad percent-encoding)', () => { + it('throws an error', done => { + TestSequences.PushInvalidPathname(history, done); + }); + }); + describe('push with a unicode path string', () => { it('creates a location with decoded properties', done => { TestSequences.PushUnicodeLocation(history, done); @@ -102,6 +108,12 @@ describe('a browser history', () => { }); }); + describe('replace with an invalid pathname (bad percent-encoding)', () => { + it('throws an error', done => { + TestSequences.ReplaceInvalidPathname(history, done); + }); + }); + describe('replace state', () => { it('calls change listeners with the new location', done => { TestSequences.ReplaceState(history, done); diff --git a/modules/__tests__/HashHistory-test.js b/modules/__tests__/HashHistory-test.js index 99f01a714..3218f50fe 100644 --- a/modules/__tests__/HashHistory-test.js +++ b/modules/__tests__/HashHistory-test.js @@ -81,6 +81,12 @@ describe('a hash history', () => { }); }); + describe('push with an invalid pathname (bad percent-encoding)', () => { + it('throws an error', done => { + TestSequences.PushInvalidPathname(history, done); + }); + }); + describe('push with a unicode path string', () => { it('creates a location with decoded properties', done => { TestSequences.PushUnicodeLocation(history, done); @@ -105,6 +111,12 @@ describe('a hash history', () => { }); }); + describe('replace with an invalid pathname (bad percent-encoding)', () => { + it('throws an error', done => { + TestSequences.ReplaceInvalidPathname(history, done); + }); + }); + describe('replace state', () => { it('calls change listeners with the new location and emits a warning', done => { TestSequences.ReplaceStateWarning(history, done); diff --git a/modules/__tests__/MemoryHistory-test.js b/modules/__tests__/MemoryHistory-test.js index 403c90ebf..176f874fb 100644 --- a/modules/__tests__/MemoryHistory-test.js +++ b/modules/__tests__/MemoryHistory-test.js @@ -75,6 +75,12 @@ describe('a memory history', () => { }); }); + describe('push with an invalid pathname (bad percent-encoding)', () => { + it('throws an error', done => { + TestSequences.PushInvalidPathname(history, done); + }); + }); + describe('push with a unicode path string', () => { it('creates a location with decoded properties', done => { TestSequences.PushUnicodeLocation(history, done); @@ -99,6 +105,12 @@ describe('a memory history', () => { }); }); + describe('replace with an invalid pathname (bad percent-encoding)', () => { + it('throws an error', done => { + TestSequences.ReplaceInvalidPathname(history, done); + }); + }); + describe('replace state', () => { it('calls change listeners with the new location', done => { TestSequences.ReplaceState(history, done); diff --git a/modules/__tests__/TestSequences/LocationPathnameAlwaysSame.js b/modules/__tests__/TestSequences/LocationPathnameAlwaysSame.js index e3d52a4f3..48facbc6d 100644 --- a/modules/__tests__/TestSequences/LocationPathnameAlwaysSame.js +++ b/modules/__tests__/TestSequences/LocationPathnameAlwaysSame.js @@ -11,16 +11,15 @@ export default function(history, done) { }, location => { expect(location).toMatchObject({ - pathname: '/%E6%AD%B4%E5%8F%B2' + pathname: '/歴史' }); - // encoded object const pathname = '/%E6%AD%B4%E5%8F%B2'; history.replace({ pathname }); }, location => { expect(location).toMatchObject({ - pathname: '/%E6%AD%B4%E5%8F%B2' + pathname: '/歴史' }); // unencoded string const pathname = '/歴史'; diff --git a/modules/__tests__/TestSequences/PushEncodedLocation.js b/modules/__tests__/TestSequences/PushEncodedLocation.js index d37695f34..f71d67109 100644 --- a/modules/__tests__/TestSequences/PushEncodedLocation.js +++ b/modules/__tests__/TestSequences/PushEncodedLocation.js @@ -9,7 +9,7 @@ export default function(history, done) { pathname: '/' }); - const pathname = '/%E6%AD%B4%E5%8F%B2'; + const pathname = '/歴史'; const search = '?%E3%82%AD%E3%83%BC=%E5%80%A4'; const hash = '#%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5'; history.push(pathname + search + hash); @@ -17,7 +17,7 @@ export default function(history, done) { (location, action) => { expect(action).toBe('PUSH'); expect(location).toMatchObject({ - pathname: '/%E6%AD%B4%E5%8F%B2', + pathname: '/歴史', search: '?%E3%82%AD%E3%83%BC=%E5%80%A4', hash: '#%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5' }); diff --git a/modules/__tests__/TestSequences/PushInvalidPathname.js b/modules/__tests__/TestSequences/PushInvalidPathname.js new file mode 100644 index 000000000..5024eebbe --- /dev/null +++ b/modules/__tests__/TestSequences/PushInvalidPathname.js @@ -0,0 +1,17 @@ +import expect from 'expect'; + +import execSteps from './execSteps'; + +export default function(history, done) { + const steps = [ + () => { + expect(() => { + history.push('/hello%'); + }).toThrow( + 'Pathname "/hello%" could not be decoded. This is likely caused by an invalid percent-encoding.' + ); + } + ]; + + execSteps(steps, history, done); +} diff --git a/modules/__tests__/TestSequences/ReplaceInvalidPathname.js b/modules/__tests__/TestSequences/ReplaceInvalidPathname.js new file mode 100644 index 000000000..5b85431f7 --- /dev/null +++ b/modules/__tests__/TestSequences/ReplaceInvalidPathname.js @@ -0,0 +1,17 @@ +import expect from 'expect'; + +import execSteps from './execSteps'; + +export default function(history, done) { + const steps = [ + () => { + expect(() => { + history.replace('/hello%'); + }).toThrow( + 'Pathname "/hello%" could not be decoded. This is likely caused by an invalid percent-encoding.' + ); + } + ]; + + execSteps(steps, history, done); +} diff --git a/modules/__tests__/TestSequences/index.js b/modules/__tests__/TestSequences/index.js index 2cb9b3329..b526cc66e 100644 --- a/modules/__tests__/TestSequences/index.js +++ b/modules/__tests__/TestSequences/index.js @@ -25,6 +25,7 @@ export { } from './LocationPathnameAlwaysSame'; export { default as NoslashHashPathCoding } from './NoslashHashPathCoding'; export { default as PushEncodedLocation } from './PushEncodedLocation'; +export { default as PushInvalidPathname } from './PushInvalidPathname'; export { default as PushNewLocation } from './PushNewLocation'; export { default as PushMissingPathname } from './PushMissingPathname'; export { default as PushSamePath } from './PushSamePath'; @@ -33,6 +34,7 @@ export { default as PushState } from './PushState'; export { default as PushStateWarning } from './PushStateWarning'; export { default as PushRelativePathname } from './PushRelativePathname'; export { default as PushUnicodeLocation } from './PushUnicodeLocation'; +export { default as ReplaceInvalidPathname } from './ReplaceInvalidPathname'; export { default as ReplaceNewLocation } from './ReplaceNewLocation'; export { default as ReplaceSamePath } from './ReplaceSamePath'; export { default as ReplaceState } from './ReplaceState';