Skip to content

Commit

Permalink
fix: only decode URL hash instead of entire URL (#13332)
Browse files Browse the repository at this point in the history
followup to #13321 / #13316

This PR ensures only the hash of the URL is decoded so that any encoded hash character in the query parameters remains encoded.
  • Loading branch information
eltigerchino authored Jan 17, 2025
1 parent 388d441 commit c43fd92
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 4 deletions.
17 changes: 15 additions & 2 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,9 @@ export async function start(_app, _target, hydrate) {
if (hydrate) {
await _hydrate(target, hydrate);
} else {
goto(app.hash ? decodeURIComponent(location.href) : location.href, { replaceState: true });
goto(app.hash ? decode_hash(new URL(location.href)) : location.href, {
replaceState: true
});
}

_start_router();
Expand Down Expand Up @@ -2432,7 +2434,7 @@ function _start_router() {
// (surprisingly!) mutates `current.url`, allowing us to
// detect it and trigger a navigation
if (current.url.hash === location.hash) {
navigate({ type: 'goto', url: new URL(decodeURIComponent(current.url.href)) });
navigate({ type: 'goto', url: decode_hash(current.url) });
}
}
});
Expand Down Expand Up @@ -2826,6 +2828,17 @@ function clone_page(page) {
};
}

/**
* @param {URL} url
* @returns {URL}
*/
function decode_hash(url) {
const new_url = new URL(url);
// Safari, for some reason, does change # to %23, when entered through the address bar
new_url.hash = decodeURIComponent(url.hash);
return new_url;
}

if (DEV) {
// Nasty hack to silence harmless warnings the user can do nothing about
const console_warn = console.warn;
Expand Down
4 changes: 2 additions & 2 deletions packages/kit/test/apps/hash-based-routing/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ test.describe('hash based navigation', () => {
});

test('navigation works with URL encoded characters', async ({ page }) => {
await page.goto('/#/%23test');
await page.goto('/?query=%23abc#/%23test');
await expect(page.locator('p')).toHaveText('home');
// hashchange event
await page.goto('/#/a%23test');
await page.goto('/?query=%23abc#/a%23test');
await expect(page.locator('p')).toHaveText('a');
});

Expand Down

0 comments on commit c43fd92

Please sign in to comment.