diff --git a/examples/basic/app.js b/examples/basic/app.js index 2e22b6763..b248d7841 100644 --- a/examples/basic/app.js +++ b/examples/basic/app.js @@ -35,6 +35,7 @@ const Home = { template: '
{{ $route.query.t }}
{{ $route.hash }}diff --git a/src/create-matcher.js b/src/create-matcher.js index ab62be430..c67538bc8 100644 --- a/src/create-matcher.js +++ b/src/create-matcher.js @@ -175,7 +175,7 @@ function matchRoute ( path: string, params: Object ): boolean { - const m = path.match(regex) + const m = decodeURI(path).match(regex) if (!m) { return false @@ -185,10 +185,9 @@ function matchRoute ( for (let i = 1, len = m.length; i < len; ++i) { const key = regex.keys[i - 1] - const val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i] if (key) { // Fix #1994: using * with props: true generates a param named 0 - params[key.name || 'pathMatch'] = val + params[key.name || 'pathMatch'] = m[i] } } diff --git a/src/history/hash.js b/src/history/hash.js index b3372e10d..e0ddf2d7c 100644 --- a/src/history/hash.js +++ b/src/history/hash.js @@ -124,18 +124,6 @@ export function getHash (): string { if (index < 0) return '' href = href.slice(index + 1) - // decode the hash but not the search or hash - // as search(query) is already decoded - // https://github.com/vuejs/vue-router/issues/2708 - const searchIndex = href.indexOf('?') - if (searchIndex < 0) { - const hashIndex = href.indexOf('#') - if (hashIndex > -1) { - href = decodeURI(href.slice(0, hashIndex)) + href.slice(hashIndex) - } else href = decodeURI(href) - } else { - href = decodeURI(href.slice(0, searchIndex)) + href.slice(searchIndex) - } return href } diff --git a/src/history/html5.js b/src/history/html5.js index 8200b3b28..9af347fe8 100644 --- a/src/history/html5.js +++ b/src/history/html5.js @@ -86,7 +86,7 @@ export class HTML5History extends History { } export function getLocation (base: string): string { - let path = decodeURI(window.location.pathname) + let path = window.location.pathname if (base && path.toLowerCase().indexOf(base.toLowerCase()) === 0) { path = path.slice(base.length) } diff --git a/test/e2e/specs/basic.js b/test/e2e/specs/basic.js index 25d3fed3f..1a623c0c6 100644 --- a/test/e2e/specs/basic.js +++ b/test/e2e/specs/basic.js @@ -9,8 +9,8 @@ module.exports = { browser .url('http://localhost:8080/basic/') .waitForElementVisible('#app', 1000) - .assert.count('li', 11) - .assert.count('li a', 11) + .assert.count('li', 12) + .assert.count('li a', 12) // assert correct href with base .assert.attributeContains('li:nth-child(1) a', 'href', '/basic/') .assert.attributeContains('li:nth-child(2) a', 'href', '/basic/foo') @@ -20,6 +20,7 @@ module.exports = { .assert.attributeContains('li:nth-child(6) a', 'href', '/basic/%C3%A9?t=%25%C3%B1') .assert.attributeContains('li:nth-child(7) a', 'href', '/basic/%C3%A9#%25%C3%B1') .assert.attributeContains('li:nth-child(8) a', 'href', '/basic/foo') + .assert.attributeContains('li:nth-child(10) a', 'href', '/basic/query/A%') .assert.containsText('.view', 'home') .click('li:nth-child(2) a') @@ -70,6 +71,15 @@ module.exports = { .assert.cssClassPresent('li:nth-child(8)', 'exact-active') .assert.attributeEquals('li:nth-child(8) a', 'class', '') + // encoded percentage as path param + // https://github.com/vuejs/vue-router/issues/2725 + .url('http://localhost:8080/basic/query/A%25') + .waitForElementVisible('#app', 1000) + .assert.containsText('.view', 'query: "A%"') + .click('li:nth-child(10) a') + .assert.urlEquals('http://localhost:8080/basic/query/A%25') + .assert.containsText('.view', 'query: "A%"') + // Listener cleanup .assert.containsText('#popstate-count', '1 popstate listeners') .click('#unmount') @@ -84,8 +94,8 @@ module.exports = { .waitForElementVisible('#app', 1000) .assert.containsText('.view', 'home') // go to foo with a delay + .click('li:nth-child(12) a') .click('li:nth-child(11) a') - .click('li:nth-child(10) a') .waitFor(300) // we should stay at /basic after the delay .assert.urlEquals('http://localhost:8080/basic/?delay=200') diff --git a/test/e2e/specs/hash-mode.js b/test/e2e/specs/hash-mode.js index 569285a23..15520313f 100644 --- a/test/e2e/specs/hash-mode.js +++ b/test/e2e/specs/hash-mode.js @@ -9,14 +9,15 @@ module.exports = { browser .url('http://localhost:8080/hash-mode/') .waitForElementVisible('#app', 1000) - .assert.count('li', 8) - .assert.count('li a', 7) + .assert.count('li', 9) + .assert.count('li a', 8) .assert.attributeContains('li:nth-child(1) a', 'href', '/hash-mode/#/') .assert.attributeContains('li:nth-child(2) a', 'href', '/hash-mode/#/foo') .assert.attributeContains('li:nth-child(3) a', 'href', '/hash-mode/#/bar') .assert.attributeContains('li:nth-child(5) a', 'href', '/hash-mode/#/%C3%A9') .assert.attributeContains('li:nth-child(6) a', 'href', '/hash-mode/#/%C3%A9/%C3%B1') .assert.attributeContains('li:nth-child(7) a', 'href', '/hash-mode/#/%C3%A9/%C3%B1?t=%25%C3%B1') + .assert.attributeContains('li:nth-child(9) a', 'href', '/hash-mode/#/query/A%') .assert.containsText('.view', 'home') .click('li:nth-child(2) a') @@ -58,6 +59,15 @@ module.exports = { .assert.containsText('.view', 'unicode: ñ') .assert.containsText('#query-t', '%') + // percentage as path param + // https://github.com/vuejs/vue-router/issues/2725 + .url('http://localhost:8080/hash-mode/#/query/A%25') + .waitForElementVisible('#app', 1000) + .assert.containsText('.view', 'query: "A%"') + .click('li:nth-child(9) a') + .assert.urlEquals('http://localhost:8080/hash-mode/#/query/A%25') + .assert.containsText('.view', 'query: "A%"') + // Listener cleanup .assert.containsText('#popstate-count', '1 popstate listeners') .click('#unmount')