]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
remove query normalization from history implementation
authorEduardo San Martin Morote <posva13@gmail.com>
Mon, 3 Feb 2020 17:25:12 +0000 (18:25 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Wed, 5 Feb 2020 13:07:17 +0000 (14:07 +0100)
playground/main.ts
src/history/common.ts
src/history/html5.ts
src/index.ts
src/router.ts
src/types/index.ts

index 97771cb183873f23258b65b8b74ee0e8993b8f22..bfdfa541962088e8218c073b4216fb8feae67ffa 100644 (file)
@@ -1,3 +1,5 @@
+// necessary for webpack
+///<reference path="../src/global.d.ts"/>
 import { createApp } from 'vue'
 import { router, routerHistory } from './router'
 import { globalState } from './store'
index 7b2d31eb27c001af11341f5c55ae7bc5b52a3c73..1a79771b5c7ef968a10b09c2a143f6f841f38d20 100644 (file)
@@ -1,19 +1,14 @@
 import { ListenerRemover } from '../types'
-import { encodeQueryProperty, encodeHash } from '../utils/encoding'
+// import { encodeQueryProperty, encodeHash } from '../utils/encoding'
 
-export type HistoryQuery = Record<string, string | string[]>
-// TODO: is it reall worth allowing null to form queries like ?q&b&c
-// When parsing using URLSearchParams, `q&c=` yield an empty string for q and c
-// I think it's okay to allow this by default and allow extending it
-// a more permissive history query
 // TODO: allow numbers
-export type RawHistoryQuery = Record<string, string | string[] | null>
+export type HistoryQuery = Record<string, string | string[]>
 
 interface HistoryLocation {
   // pathname section
   path: string
   // search string parsed
-  query?: RawHistoryQuery
+  query?: HistoryQuery
   // hash with the #
   hash?: string
 }
@@ -119,7 +114,7 @@ export function parseURL(location: string): HistoryLocationNormalized {
     )
 
     // TODO: can we remove the normalize call?
-    query = normalizeQuery(parseQuery(searchString))
+    query = parseQuery(searchString)
   }
 
   if (hashPos > -1) {
@@ -139,34 +134,16 @@ export function parseURL(location: string): HistoryLocationNormalized {
   }
 }
 
-// TODO: the encoding would be handled at a router level instead where encoding functions can be customized
-// that way the matcher can encode/decode params properly
-
-// function safeDecodeUriComponent(value: string): string {
-//   try {
-//     value = decodeURIComponent(value)
-//   } catch (err) {
-//     // TODO: handling only URIError?
-//     console.warn(
-//       `[vue-router] error decoding query "${value}". Keeping the original value.`
-//     )
-//   }
-
-//   return value
-// }
-
-// function safeEncodeUriComponent(value: string): string {
-//   try {
-//     value = encodeURIComponent(value)
-//   } catch (err) {
-//     // TODO: handling only URIError?
-//     console.warn(
-//       `[vue-router] error encoding query "${value}". Keeping the original value.`
-//     )
-//   }
+/**
+ * Stringify a URL object
+ * @param location
+ */
+export function stringifyURL(location: HistoryLocation): string {
+  let url = location.path
+  let query = location.query ? stringifyQuery(location.query) : ''
 
-//   return value
-// }
+  return url + (query && '?' + query) + (location.hash || '')
+}
 
 /**
  * Transform a queryString into a query object. Accept both, a version with the leading `?` and without
@@ -196,23 +173,11 @@ export function parseQuery(search: string): HistoryQuery {
   }
   return query
 }
-
-/**
- * Stringify a URL object
- * @param location
- */
-export function stringifyURL(location: HistoryLocation): string {
-  let url = location.path
-  let query = location.query ? stringifyQuery(location.query) : ''
-
-  return url + (query && '?' + query) + encodeHash(location.hash || '')
-}
-
 /**
  * Stringify an object query. Works like URLSearchParams. Doesn't prepend a `?`
  * @param query
  */
-export function stringifyQuery(query: RawHistoryQuery): string {
+export function stringifyQuery(query: HistoryQuery): string {
   let search = ''
   for (const key in query) {
     if (search.length > 1) search += '&'
@@ -222,36 +187,19 @@ export function stringifyQuery(query: RawHistoryQuery): string {
       search += key
       continue
     }
-    const encodedKey = encodeQueryProperty(key)
+    // const encodedKey = encodeQueryProperty(key)
     let values: string[] = Array.isArray(value) ? value : [value]
-    const encodedValues = values.map(encodeQueryProperty)
+    // const encodedValues = values.map(encodeQueryProperty)
 
-    search += `${encodedKey}=${values[0]}`
+    search += `${key}=${values[0]}`
     for (let i = 1; i < values.length; i++) {
-      search += `&${encodedKey}=${encodedValues[i]}`
+      search += `&${key}=${values[i]}`
     }
   }
 
   return search
 }
 
-export function normalizeQuery(query: RawHistoryQuery): HistoryQuery {
-  // TODO: properly test
-  const normalizedQuery: HistoryQuery = {}
-  for (const key in query) {
-    const value = query[key]
-    if (value === null) normalizedQuery[key] = ''
-    else normalizedQuery[key] = value
-  }
-  return normalizedQuery
-}
-
-// use regular decodeURI
-// Use a renamed export instead of global.decodeURI
-// to support node and browser at the same time
-const originalDecodeURI = decodeURI
-export { originalDecodeURI as decodeURI }
-
 /**
  * Normalize a History location object or string into a HistoryLocationNoramlized
  * @param location
@@ -264,7 +212,7 @@ export function normalizeLocation(
     return {
       fullPath: stringifyURL(location),
       path: location.path,
-      query: location.query ? normalizeQuery(location.query) : {},
+      query: location.query || {},
       hash: location.hash || '',
     }
 }
index 51c0e034a90ea0594b6d36bf9a5a6accb7887bfe..486a190ae0c5582e2a0fedfb75ace780644c5f6c 100644 (file)
@@ -1,14 +1,12 @@
 import {
   RouterHistory,
   NavigationCallback,
-  parseQuery,
   normalizeLocation,
   stripBase,
   NavigationType,
   NavigationDirection,
   HistoryLocationNormalized,
   HistoryState,
-  parseURL,
   RawHistoryLocation,
   ValueContainer,
 } from './common'
@@ -30,7 +28,6 @@ interface StateEntry {
 
 /**
  * Creates a noramlized history location from a window.location object
- * TODO: encoding is not handled like this
  * @param location
  */
 function createCurrentLocation(
@@ -41,15 +38,10 @@ function createCurrentLocation(
   // allows hash based url
   if (base.indexOf('#') > -1) {
     // prepend the starting slash to hash so the url starts with /#
-    return parseURL(stripBase('/' + hash, base))
+    return normalizeLocation(stripBase('/' + hash, base))
   }
   const path = stripBase(pathname, base)
-  return {
-    fullPath: path + search + hash,
-    path,
-    query: parseQuery(search),
-    hash: hash,
-  }
+  return normalizeLocation(path + search + hash)
 }
 
 function useHistoryListeners(
index 4f623a7ffa279dd2ac00625bc4e7429205c8437f..6fadc302a9ffa6578bd245c6b6cb724a2f33f884 100644 (file)
@@ -9,9 +9,6 @@ import {
 } from './types'
 import { onBeforeRouteLeave } from './navigationGuards'
 
-// necessary for webpack
-///<reference path="global.d.ts"/>
-
 declare module 'vue' {
   function inject<T>(key: InjectionKey<T> | string): T | undefined
   function inject<T>(key: InjectionKey<T> | string, defaultValue: T): T
index 089d0bc49c93f0b6e52565f29a54cbbc2e7d6c9f..b598643da677205f14bd54e4bd7bfe56217d62e8 100644 (file)
@@ -12,12 +12,7 @@ import {
   TODO,
   Immutable,
 } from './types'
-import {
-  RouterHistory,
-  normalizeLocation,
-  stringifyURL,
-  normalizeQuery,
-} from './history/common'
+import { RouterHistory, normalizeLocation } from './history/common'
 import {
   ScrollToPosition,
   ScrollPosition,
@@ -31,8 +26,7 @@ import {
 } from './errors'
 import { extractComponentsGuards, guardToPromiseFn } from './utils'
 import { useCallbacks } from './utils/callbacks'
-import { encodeParam } from './utils/encoding'
-import { decode } from './utils/encoding'
+import { encodeParam, decode } from './utils/encoding'
 import { ref, Ref, markNonReactive, nextTick, App } from 'vue'
 import { RouteRecordMatched } from './matcher/types'
 import Link from './components/Link'
@@ -169,13 +163,11 @@ export function createRouter({
       // target location normalized, used if we want to redirect again
       const normalizedLocation: RouteLocationNormalized = {
         ...matchedRoute.normalizedLocation,
-        fullPath: stringifyURL({
+        ...normalizeLocation({
           path: matchedRoute.normalizedLocation.path,
           query: location.query,
           hash: location.hash,
         }),
-        query: normalizeQuery(location.query || {}),
-        hash: location.hash,
         redirectedFrom,
         meta: {},
       }
@@ -205,7 +197,7 @@ export function createRouter({
         return resolveLocation(
           {
             ...newLocation,
-            query: normalizeQuery(newLocation.query || {}),
+            query: newLocation.query || {},
             hash: newLocation.hash || '',
           },
           currentLocation,
@@ -215,7 +207,7 @@ export function createRouter({
         return resolveLocation(
           {
             ...redirect,
-            query: normalizeQuery(redirect.query || {}),
+            query: redirect.query || {},
             hash: redirect.hash || '',
           },
           currentLocation,
@@ -384,9 +376,13 @@ export function createRouter({
       record.leaveGuards = []
     }
 
-    // change URL only if the user did a push/replace
+    // only consider as push if it's not the first navigation
+    const isFirstNavigation = from === START_LOCATION_NORMALIZED
+
+    // change URL only if the user did a push/replace and if it's not the initial navigation because
+    // it's just reflecting the url
     if (isPush) {
-      if (replace) history.replace(toLocation)
+      if (replace || isFirstNavigation) history.replace(toLocation)
       else history.push(toLocation)
     }
 
index 964f5755ef3d6259800c55a311972e5731e3226d..08cfced88f5e61e57c0dc63cf58202f194017b95 100644 (file)
@@ -1,4 +1,4 @@
-import { HistoryQuery, RawHistoryQuery } from '../history/common'
+import { HistoryQuery } from '../history/common'
 import { PathParserOptions } from '../matcher/path-parser-ranker'
 import { markNonReactive } from 'vue'
 import { RouteRecordMatched } from '../matcher/types'
@@ -20,7 +20,7 @@ export type ListenerRemover = () => void
 export type RouteParams = Record<string, string | string[]>
 
 export interface RouteQueryAndHash {
-  query?: RawHistoryQuery
+  query?: HistoryQuery
   hash?: string
 }
 export interface LocationAsPath {