From 820bd33ef2255faef8d516a0c51c0f3dd3959bcd Mon Sep 17 00:00:00 2001 From: Tom Rumpf <35841182+tomcru@users.noreply.github.com> Date: Mon, 26 Feb 2024 23:29:00 +0100 Subject: [PATCH 1/2] fix: prevent redundant patching of History API methods The previous implementation of patching the History API methods (pushState and replaceState) was causing them to increasingly nest within patched versions of themselves. To fix this, a new flag `isHistoryPatched` was introduced to prevent redundant patching. The `stopProgressOnHistoryUpdate` function now checks if the flag is already set before applying the patch. Additionally, the flag is set to `true` after the patching is done to ensure it is only applied once. Reference: https://github.com/TheSGJ/nextjs-toploader/pull/68 --- src/index.tsx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 66b8607..10c725b 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -128,23 +128,36 @@ const HolyLoader = ({ } catch (error) {} }; + /** + * Flag to prevent redundant patching of History API methods. + * This is essential to avoid pushState & replaceState increasingly nesting + * withing patched versions of itself + */ + let isHistoryPatched = false; + /** * Enhances browser history methods (pushState and replaceState) to ensure that the * progress indicator is appropriately halted when navigating through single-page applications */ const stopProgressOnHistoryUpdate = (): void => { + if (isHistoryPatched) { + return; + } + const originalPushState = history.pushState.bind(history); history.pushState = (...args) => { stopProgress(); - originalPushState(...args); + originalPushState.apply(history, args); }; // This is crucial for Next.js Link components using the 'replace' prop. const originalReplaceState = history.replaceState.bind(history); history.replaceState = (...args) => { stopProgress(); - originalReplaceState(...args); + originalReplaceState.apply(history, args); }; + + isHistoryPatched = true; }; /** @@ -173,7 +186,6 @@ const HolyLoader = ({ } startProgress(); - stopProgressOnHistoryUpdate(); } catch (error) { stopProgress(); } @@ -192,6 +204,7 @@ const HolyLoader = ({ }); document.addEventListener('click', handleClick); + stopProgressOnHistoryUpdate(); } catch (error) {} return () => { From 3b535935ce3879d34c6285437f88297a84b0b92d Mon Sep 17 00:00:00 2001 From: Tom Rumpf <35841182+tomcru@users.noreply.github.com> Date: Mon, 26 Feb 2024 23:31:38 +0100 Subject: [PATCH 2/2] fix: remove unnecessary use of apply in history.pushState and history.replaceState calls --- src/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 10c725b..12b0936 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -147,14 +147,14 @@ const HolyLoader = ({ const originalPushState = history.pushState.bind(history); history.pushState = (...args) => { stopProgress(); - originalPushState.apply(history, args); + originalPushState(...args); }; // This is crucial for Next.js Link components using the 'replace' prop. const originalReplaceState = history.replaceState.bind(history); history.replaceState = (...args) => { stopProgress(); - originalReplaceState.apply(history, args); + originalReplaceState(...args); }; isHistoryPatched = true;