vuejs / router

🚦 The official router for Vue.js

Home Page:https://router.vuejs.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

hash decode not match the later encode

zcqno1 opened this issue · comments

Reproduction

https://jsfiddle.net/qhn7gka8/

Steps to reproduce the bug

  1. route like /test#/?redirect=%2F%3Fid%3D1%23%2Fabc (just `/test#/?redirect=${encodeURIComponent('/?id=1#/abc')}`)
  2. do replace the upper route, the final route.fullpath turn to /test#/?redirect=/?id=1#/abc, that's unexpected
  3. push works well.

Expected behavior

the hash of route remain its original encode

Actual behavior

hash's original encode lost

Additional information

posible reason.

The hash part of route is decode in the parseURL function.

hash: decode(hash),

decode uses decodeURIComponent, which would decode the /?.

After doing a replace action, it calls parseURL first, and then calls resolve(to) later.

const targetLocation: RouteLocation = (pendingLocation = resolve(to))

In function resolve, hash is encode.
However, encodeHash use encodeURI indexof encodeURIComponent, so the hash would never be encoded to the original hash if there's characters /? in it.

hash: encodeHash(hash),

export function encodeHash(text: string): string {

/**
 * Encode characters that need to be encoded on the path, search and hash
 * sections of the URL.
 *
 * @internal
 * @param text - string to encode
 * @returns encoded string
 */
function commonEncode(text: string | number): string {
  return encodeURI('' + text)
    .replace(ENC_PIPE_RE, '|')
    .replace(ENC_BRACKET_OPEN_RE, '[')
    .replace(ENC_BRACKET_CLOSE_RE, ']')
}

/**
 * Encode characters that need to be encoded on the hash section of the URL.
 *
 * @param text - string to encode
 * @returns encoded string
 */
export function encodeHash(text: string): string {
  return commonEncode(text)
    .replace(ENC_CURLY_OPEN_RE, '{')
    .replace(ENC_CURLY_CLOSE_RE, '}')
    .replace(ENC_CARET_RE, '^')
}

Maybe decode(hash) in function parseURL should use decodeURI instead of decodeURIComponent.

see #2060 and its pr #2061

The inconsistency in route.fullPath is a bit inconvenient but as long as the route.hash (and the other properties) is consistent, it's okay. In future major versions it will be possible to migrate to use the native URL constructor and get a more flexible behavior but it wasn't possible to do so when the router was initially written. Changing this now would be a breaking change as the router intentionally normalizes the hash (and other properties) to always be decoded. The fullPath, on the other hand, can vary depending on the browser and the target location, which is what you are seeing here.

So technically, this is fixable with #2189 but I wouldn't rely on route.fullPath being consistent as it can vary depending of environments and other factors

I had to revert this because it breaks other behaviors... This will be a wontfix until we use URL