Skip to content

Commit

Permalink
fix: don't stash away original history methods so other libs can mo…
Browse files Browse the repository at this point in the history
…nkeypatch it (#11657)
  • Loading branch information
dummdidumm committed Jan 17, 2024
1 parent b4e1095 commit 5a1fc41
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/bright-moose-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sveltejs/kit": patch
---

fix: don't stash away original `history` methods so other libs can monkeypatch it
30 changes: 18 additions & 12 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,29 +64,37 @@ const scroll_positions = storage.get(SCROLL_KEY) ?? {};
*/
const snapshots = storage.get(SNAPSHOT_KEY) ?? {};

const original_push_state = BROWSER ? history.pushState : () => {};
const original_replace_state = BROWSER ? history.replaceState : () => {};

if (DEV && BROWSER) {
let warned = false;

const warn = () => {
if (warned) return;

// Rather than saving a pointer to the original history methods, which would prevent monkeypatching by other libs,
// inspect the stack trace to see if we're being called from within SvelteKit.
let stack = new Error().stack?.split('\n');
if (!stack) return;
if (!stack[0].includes('https:') && !stack[0].includes('http:')) stack = stack.slice(1); // Chrome includes the error message in the stack
stack = stack.slice(2); // remove `warn` and the place where `warn` was called
if (stack[0].includes(import.meta.url)) return;

warned = true;

console.warn(
"Avoid using `history.pushState(...)` and `history.replaceState(...)` as these will conflict with SvelteKit's router. Use the `pushState` and `replaceState` imports from `$app/navigation` instead."
);
};

const push_state = history.pushState;
history.pushState = (...args) => {
warn();
return original_push_state.apply(history, args);
return push_state.apply(history, args);
};

const replace_state = history.replaceState;
history.replaceState = (...args) => {
warn();
return original_replace_state.apply(history, args);
return replace_state.apply(history, args);
};
}

Expand Down Expand Up @@ -252,8 +260,7 @@ export async function start(_app, _target, hydrate) {
current_history_index = current_navigation_index = Date.now();

// create initial history entry, so we can return here
original_replace_state.call(
history,
history.replaceState(
{
...history.state,
[HISTORY_INDEX]: current_history_index,
Expand Down Expand Up @@ -1296,7 +1303,7 @@ async function navigate({
[STATES_KEY]: state
};

const fn = replace_state ? original_replace_state : original_push_state;
const fn = replace_state ? history.replaceState : history.pushState;
fn.call(history, entry, '', url);

if (!replace_state) {
Expand Down Expand Up @@ -1812,7 +1819,7 @@ export function pushState(url, state) {
[STATES_KEY]: state
};

original_push_state.call(history, opts, '', resolve_url(url));
history.pushState(opts, '', resolve_url(url));

page = { ...page, state };
root.$set({ page });
Expand Down Expand Up @@ -1849,7 +1856,7 @@ export function replaceState(url, state) {
[STATES_KEY]: state
};

original_replace_state.call(history, opts, '', resolve_url(url));
history.replaceState(opts, '', resolve_url(url));

page = { ...page, state };
root.$set({ page });
Expand Down Expand Up @@ -2180,8 +2187,7 @@ function _start_router() {
// we need to update history, otherwise we have to leave it alone
if (hash_navigating) {
hash_navigating = false;
original_replace_state.call(
history,
history.replaceState(
{
...history.state,
[HISTORY_INDEX]: ++current_history_index,
Expand Down
1 change: 1 addition & 0 deletions packages/kit/src/runtime/client/fetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export function unlock_fetch() {
if (DEV && BROWSER) {
let can_inspect_stack_trace = false;

// detect whether async stack traces work
const check_stack_trace = async () => {
const stack = /** @type {string} */ (new Error().stack);
can_inspect_stack_trace = stack.includes('check_stack_trace');
Expand Down

0 comments on commit 5a1fc41

Please sign in to comment.