From 2730df8e0cbca7fb3d8df3e740c31086e68c7a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Este=CC=81vez?= Date: Tue, 15 Sep 2020 15:23:47 +0200 Subject: [PATCH 1/3] fix(#2725): remove duplicated decodeURIComponent --- examples/basic/app.js | 5 ++++- examples/hash-mode/app.js | 5 ++++- src/create-matcher.js | 3 +-- test/e2e/specs/basic.js | 14 ++++++++++++-- test/e2e/specs/hash-mode.js | 14 ++++++++++++-- 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/examples/basic/app.js b/examples/basic/app.js index ba13679f2..29a9b8553 100644 --- a/examples/basic/app.js +++ b/examples/basic/app.js @@ -35,6 +35,7 @@ const Home = { template: '
home
' } const Foo = { template: '
foo
' } const Bar = { template: '
bar
' } const Unicode = { template: '
unicode
' } +const Query = { template: '
query: {{ $route.params.q }}
' } // 3. Create the router const router = new VueRouter({ @@ -44,7 +45,8 @@ const router = new VueRouter({ { path: '/', component: Home }, { path: '/foo', component: Foo }, { path: '/bar', component: Bar }, - { path: '/é', component: Unicode } + { path: '/é', component: Unicode }, + { path: '/query/:q', component: Query } ] }) @@ -73,6 +75,7 @@ const vueInstance = new Vue({
  • /foo (replace)
  • +
  • /query/A%
  • {{ n }}
    diff --git a/examples/hash-mode/app.js b/examples/hash-mode/app.js index 48b9ab1d6..47be4785b 100644 --- a/examples/hash-mode/app.js +++ b/examples/hash-mode/app.js @@ -35,6 +35,7 @@ const Home = { template: '
    home
    ' } const Foo = { template: '
    foo
    ' } const Bar = { template: '
    bar
    ' } const Unicode = { template: '
    unicode: {{ $route.params.unicode }}
    ' } +const Query = { template: '
    query: {{ $route.params.q }}
    ' } // 3. Create the router const router = new VueRouter({ @@ -45,7 +46,8 @@ const router = new VueRouter({ { path: '/foo', component: Foo }, { path: '/bar', component: Bar }, { path: '/é', component: Unicode }, - { path: '/é/:unicode', component: Unicode } + { path: '/é/:unicode', component: Unicode }, + { path: '/query/:q', component: Query } ] }) @@ -66,6 +68,7 @@ const vueInstance = new Vue({
  • /é/ñ
  • /é/ñ?t=%ñ
  • /é/ñ#é
  • +
  • /query/A%
  • {{ $route.query.t }}
    {{ $route.hash }}
    diff --git a/src/create-matcher.js b/src/create-matcher.js index ab62be430..5b29f4d01 100644 --- a/src/create-matcher.js +++ b/src/create-matcher.js @@ -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/test/e2e/specs/basic.js b/test/e2e/specs/basic.js index f4d7d6f51..fb64013d3 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', 9) - .assert.count('li a', 9) + .assert.count('li', 10) + .assert.count('li a', 10) // 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%25') .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') diff --git a/test/e2e/specs/hash-mode.js b/test/e2e/specs/hash-mode.js index 569285a23..830c98997 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%25') .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') From 6ab3769345bd037f5b3b6326849899f763f0c7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Este=CC=81vez?= Date: Wed, 16 Sep 2020 13:10:32 +0200 Subject: [PATCH 2/3] fix(#2725): remove duplicated decodeURIComponent --- examples/basic/app.js | 4 ++-- examples/hash-mode/app.js | 4 ++-- test/e2e/specs/basic.js | 6 +++--- test/e2e/specs/hash-mode.js | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/basic/app.js b/examples/basic/app.js index 29a9b8553..90dcda670 100644 --- a/examples/basic/app.js +++ b/examples/basic/app.js @@ -35,7 +35,7 @@ const Home = { template: '
    home
    ' } const Foo = { template: '
    foo
    ' } const Bar = { template: '
    bar
    ' } const Unicode = { template: '
    unicode
    ' } -const Query = { template: '
    query: {{ $route.params.q }}
    ' } +const Query = { template: '
    query: "{{ $route.params.q }}"
    ' } // 3. Create the router const router = new VueRouter({ @@ -75,7 +75,7 @@ const vueInstance = new Vue({
  • /foo (replace)
  • -
  • /query/A%
  • +
  • /query/A%
  • {{ n }}
    diff --git a/examples/hash-mode/app.js b/examples/hash-mode/app.js index 47be4785b..a9cce3a9a 100644 --- a/examples/hash-mode/app.js +++ b/examples/hash-mode/app.js @@ -35,7 +35,7 @@ const Home = { template: '
    home
    ' } const Foo = { template: '
    foo
    ' } const Bar = { template: '
    bar
    ' } const Unicode = { template: '
    unicode: {{ $route.params.unicode }}
    ' } -const Query = { template: '
    query: {{ $route.params.q }}
    ' } +const Query = { template: '
    query: "{{ $route.params.q }}"
    ' } // 3. Create the router const router = new VueRouter({ @@ -68,7 +68,7 @@ const vueInstance = new Vue({
  • /é/ñ
  • /é/ñ?t=%ñ
  • /é/ñ#é
  • -
  • /query/A%
  • +
  • /query/A%
  • {{ $route.query.t }}
    {{ $route.hash }}
    diff --git a/test/e2e/specs/basic.js b/test/e2e/specs/basic.js index fb64013d3..c383ba040 100644 --- a/test/e2e/specs/basic.js +++ b/test/e2e/specs/basic.js @@ -20,7 +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%25') + .assert.attributeContains('li:nth-child(10) a', 'href', '/basic/query/A%') .assert.containsText('.view', 'home') .click('li:nth-child(2) a') @@ -75,10 +75,10 @@ module.exports = { // https://github.com/vuejs/vue-router/issues/2725 .url('http://localhost:8080/basic/query/A%25') .waitForElementVisible('#app', 1000) - .assert.containsText('.view', 'query: A%') + .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%') + .assert.containsText('.view', 'query: "A%"') // Listener cleanup .assert.containsText('#popstate-count', '1 popstate listeners') diff --git a/test/e2e/specs/hash-mode.js b/test/e2e/specs/hash-mode.js index 830c98997..15520313f 100644 --- a/test/e2e/specs/hash-mode.js +++ b/test/e2e/specs/hash-mode.js @@ -17,7 +17,7 @@ module.exports = { .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%25') + .assert.attributeContains('li:nth-child(9) a', 'href', '/hash-mode/#/query/A%') .assert.containsText('.view', 'home') .click('li:nth-child(2) a') @@ -63,10 +63,10 @@ module.exports = { // 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%') + .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%') + .assert.containsText('.view', 'query: "A%"') // Listener cleanup .assert.containsText('#popstate-count', '1 popstate listeners') From 8018705735ba90354c5cd8edddd94372463d5a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Este=CC=81vez?= Date: Tue, 29 Sep 2020 14:01:28 +0200 Subject: [PATCH 3/3] fix(#2725): remove duplicated decodeURIComponent --- examples/basic/app.js | 2 +- examples/hash-mode/app.js | 2 +- src/create-matcher.js | 2 +- src/history/hash.js | 12 ------------ src/history/html5.js | 2 +- 5 files changed, 4 insertions(+), 16 deletions(-) diff --git a/examples/basic/app.js b/examples/basic/app.js index 90dcda670..6c35d1310 100644 --- a/examples/basic/app.js +++ b/examples/basic/app.js @@ -75,7 +75,7 @@ const vueInstance = new Vue({
  • /foo (replace)
  • -
  • /query/A%
  • +
  • /query/A%
  • {{ n }}
    diff --git a/examples/hash-mode/app.js b/examples/hash-mode/app.js index a9cce3a9a..80a2056ab 100644 --- a/examples/hash-mode/app.js +++ b/examples/hash-mode/app.js @@ -68,7 +68,7 @@ const vueInstance = new Vue({
  • /é/ñ
  • /é/ñ?t=%ñ
  • /é/ñ#é
  • -
  • /query/A%
  • +
  • /query/A%
  • {{ $route.query.t }}
    {{ $route.hash }}
    diff --git a/src/create-matcher.js b/src/create-matcher.js index 5b29f4d01..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 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) }