diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 5b241f0bd8b3..729be9d19174 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -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(); @@ -2407,7 +2409,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) }); } } }); @@ -2801,6 +2803,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; diff --git a/packages/kit/test/apps/hash-based-routing/test/test.js b/packages/kit/test/apps/hash-based-routing/test/test.js index 6743639fec2c..23666ed5e562 100644 --- a/packages/kit/test/apps/hash-based-routing/test/test.js +++ b/packages/kit/test/apps/hash-based-routing/test/test.js @@ -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'); });