diff --git a/.changeset/great-schools-cross.md b/.changeset/great-schools-cross.md new file mode 100644 index 000000000000..4280708e2cf9 --- /dev/null +++ b/.changeset/great-schools-cross.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: ensure `beforeNavigate` works on other navigations after clicking a download link diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 0cd7d8a0ab66..ece6c82e4022 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -140,10 +140,16 @@ function clear_onward_history(current_history_index, current_navigation_index) { * Returns a `Promise` that never resolves (to prevent any * subsequent work, e.g. history manipulation, from happening) * @param {URL} url + * @returns {Promise} */ function native_navigation(url) { location.href = url.href; - return new Promise(() => {}); + return new Promise((resolve) => { + // if we're still on the same page after setting location.href, it was probably a download + if (location.href !== url.href) { + resolve(undefined); + } + }); } /** @@ -1429,6 +1435,7 @@ async function navigate({ } // store this before calling `accept()`, which may change the index + // @ts-ignore ts doesn't know that we're calling `start()` which sets the current_history_index const previous_history_index = current_history_index; const previous_navigation_index = current_navigation_index; @@ -1479,6 +1486,13 @@ async function navigate({ 404 ); } + + // if we're still on the same page, it's likely it was a download link + if (!navigation_result) { + stores.navigating.set(null); + nav.fulfil(undefined); + return; + } } // if this is an internal navigation intent, use the normalized @@ -2248,6 +2262,9 @@ function _start_router() { before_navigate_callbacks.forEach((fn) => fn(navigation)); } + // We need to reset the flag manually here because clicking on an + // implicit download link does not reset it for the next navigation. + is_navigating = false; if (should_block) { e.preventDefault(); diff --git a/packages/kit/test/apps/basics/src/routes/navigation-lifecycle/before-navigate/download/+server.js b/packages/kit/test/apps/basics/src/routes/navigation-lifecycle/before-navigate/download/+server.js new file mode 100644 index 000000000000..cbd6a2aae8e8 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/navigation-lifecycle/before-navigate/download/+server.js @@ -0,0 +1,7 @@ +export function GET() { + return new Response('ok', { + headers: { + 'Content-Disposition': 'attachment' + } + }); +} diff --git a/packages/kit/test/apps/basics/src/routes/navigation-lifecycle/before-navigate/prevent-navigation/+page.svelte b/packages/kit/test/apps/basics/src/routes/navigation-lifecycle/before-navigate/prevent-navigation/+page.svelte index adc5b6404c20..186ced228dba 100644 --- a/packages/kit/test/apps/basics/src/routes/navigation-lifecycle/before-navigate/prevent-navigation/+page.svelte +++ b/packages/kit/test/apps/basics/src/routes/navigation-lifecycle/before-navigate/prevent-navigation/+page.svelte @@ -1,13 +1,21 @@