Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hash decode not match the later encode #2187

Closed
zcqno1 opened this issue Mar 25, 2024 · 2 comments · Fixed by #2189
Closed

hash decode not match the later encode #2187

zcqno1 opened this issue Mar 25, 2024 · 2 comments · Fixed by #2189
Labels
wontfix This will not be worked on

Comments

@zcqno1
Copy link

zcqno1 commented Mar 25, 2024

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

Copy link
Member

posva commented Mar 25, 2024

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

posva added a commit that referenced this issue Apr 17, 2024
* fix: avoid normalizing the fullPath

Close #2187

* test: add test
@posva
Copy link
Member

posva commented Apr 18, 2024

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

@posva posva closed this as not planned Won't fix, can't repro, duplicate, stale Apr 18, 2024
@posva posva added the wontfix This will not be worked on label Apr 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wontfix This will not be worked on
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants