]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix(encoding): encode partial params
authorEduardo San Martin Morote <posva13@gmail.com>
Thu, 6 Aug 2020 13:29:40 +0000 (15:29 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Thu, 6 Aug 2020 13:29:40 +0000 (15:29 +0200)
__tests__/urlEncoding.spec.ts
src/router.ts

index 3e4ca5e5c00a5405bae4bc82640c8c382da37bae..e9653af9a7201ac6dfc4018b8112c66a69ba7413 100644 (file)
@@ -12,6 +12,7 @@ const routes: RouteRecordRaw[] = [
   { path: '/to-p/:p', redirect: to => `/p/${to.params.p}` },
   { path: '/p/:p', component: components.Bar, name: 'params' },
   { path: '/p/:p+', component: components.Bar, name: 'repeat' },
+  { path: '/optional/:a/:b?', component: components.Bar, name: 'optional' },
 ]
 
 function createRouter() {
@@ -42,7 +43,8 @@ describe('URL Encoding', () => {
     const router = createRouter()
     await router.push('/p/bar')
     await router.push({ params: { p: 'foo' } })
-    expect(encoding.encodeParam).toHaveBeenCalledTimes(1)
+    expect(encoding.encodeParam).toHaveBeenCalledTimes(2)
+    expect(encoding.encodeParam).toHaveBeenCalledWith('bar')
     expect(encoding.encodeParam).toHaveBeenCalledWith('foo')
   })
 
@@ -75,16 +77,17 @@ describe('URL Encoding', () => {
     expect(encoding.decode).toHaveBeenNthCalledWith(2, 'bar', 1, ['foo', 'bar'])
   })
 
-  it('keeps decoded values in params', async () => {
+  it('decodes values in params', async () => {
     // @ts-ignore: override to make the difference
     encoding.decode = () => 'd'
     // @ts-ignore
     encoding.encodeParam = () => 'e'
     const router = createRouter()
-    await router.push({ name: 'params', params: { p: '%' } })
+    await router.push({ name: 'optional', params: { a: 'a%' } })
+    await router.push({ params: { b: 'b%' } })
     expect(router.currentRoute.value).toMatchObject({
-      fullPath: '/p/e',
-      params: { p: '%' },
+      fullPath: '/optional/e/e',
+      params: { b: 'd', a: 'd' },
     })
   })
 
index c8a4a58bbd925aec9c91c484547079bd91863144..f10f04a6fe8bc5d42aea918ec676c6dfdc1b8d1a 100644 (file)
@@ -239,10 +239,11 @@ export function createRouter(options: RouterOptions): Router {
 
   function resolve(
     rawLocation: Readonly<RouteLocationRaw>,
-    currentLocation?: Readonly<RouteLocationNormalizedLoaded>
+    currentLocation?: RouteLocationNormalizedLoaded
   ): RouteLocation & { href: string } {
     // const objectLocation = routerLocationAsObject(rawLocation)
-    currentLocation = currentLocation || currentRoute.value
+    // we create a copy to modify it later
+    currentLocation = { ...(currentLocation || currentRoute.value) }
     if (typeof rawLocation === 'string') {
       let locationNormalized = parseURL(
         parseQuery,
@@ -293,9 +294,13 @@ export function createRouter(options: RouterOptions): Router {
         path: parseURL(parseQuery, rawLocation.path, currentLocation.path).path,
       })
     } else {
+      // pass encoded values to the matcher so it can produce encoded path and fullPath
       matcherLocation = assign({}, rawLocation, {
         params: encodeParams(rawLocation.params),
       })
+      // current location params are decoded, we need to encode them in case the
+      // matcher merges the params
+      currentLocation.params = encodeParams(currentLocation.params)
     }
 
     let matchedRoute = matcher.resolve(matcherLocation, currentLocation)
@@ -307,11 +312,9 @@ export function createRouter(options: RouterOptions): Router {
       )
     }
 
-    // put back the unencoded params as given by the user (avoid the cost of decoding them)
-    matchedRoute.params =
-      'params' in rawLocation
-        ? normalizeParams(rawLocation.params)
-        : decodeParams(matchedRoute.params)
+    // decoding them) the matcher might have merged current location params so
+    // we need to run the decoding again
+    matchedRoute.params = normalizeParams(decodeParams(matchedRoute.params))
 
     const fullPath = stringifyURL(
       stringifyQuery,