Skip to content

Commit

Permalink
fix: update page store when URL hash is changed from the address bar (#…
Browse files Browse the repository at this point in the history
…10202)

Fixes #9374
Closes #9548
  • Loading branch information
plbstl authored Jul 5, 2023
1 parent c1ad5b2 commit 4d7f38f
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/hungry-ghosts-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

fix: update page store when URL hash is changed from the address bar
57 changes: 36 additions & 21 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { DEV } from 'esm-env';
import { onMount, tick } from 'svelte';
import {
make_trackable,
decode_pathname,
add_data_suffix,
decode_params,
normalize_path,
add_data_suffix
decode_pathname,
make_trackable,
normalize_path
} from '../../utils/url.js';
import {
initial_fetch,
lock_fetch,
native_fetch,
subsequent_fetch,
unlock_fetch
} from './fetcher.js';
import { parse } from './parse.js';
import * as storage from './session-storage.js';
import {
find_anchor,
get_base_uri,
Expand All @@ -15,25 +24,16 @@ import {
is_external_url,
scroll_state
} from './utils.js';
import * as storage from './session-storage.js';
import {
lock_fetch,
unlock_fetch,
initial_fetch,
subsequent_fetch,
native_fetch
} from './fetcher.js';
import { parse } from './parse.js';

import { base } from '__sveltekit/paths';
import { HttpError, Redirect } from '../control.js';
import { stores } from './singletons.js';
import { unwrap_promises } from '../../utils/promises.js';
import * as devalue from 'devalue';
import { INDEX_KEY, PRELOAD_PRIORITIES, SCROLL_KEY, SNAPSHOT_KEY } from './constants.js';
import { validate_page_exports } from '../../utils/exports.js';
import { compact } from '../../utils/array.js';
import { validate_page_exports } from '../../utils/exports.js';
import { unwrap_promises } from '../../utils/promises.js';
import { HttpError, Redirect } from '../control.js';
import { INVALIDATED_PARAM, validate_depends } from '../shared.js';
import { INDEX_KEY, PRELOAD_PRIORITIES, SCROLL_KEY, SNAPSHOT_KEY } from './constants.js';
import { stores } from './singletons.js';

let errored = false;

Expand Down Expand Up @@ -1555,9 +1555,7 @@ export function create_client(app, target) {

update_scroll_positions(current_history_index);

current.url = url;
stores.page.set({ ...page, url });
stores.page.notify();
update_url(url);

if (!options.replace_state) return;

Expand Down Expand Up @@ -1670,6 +1668,14 @@ export function create_client(app, target) {
type: 'popstate',
delta
});
} else {
// since popstate event is also emitted when an anchor referencing the same
// document is clicked, we have to check that the router isn't already handling
// the navigation. otherwise we would be updating the page store twice.
if (!hash_navigating) {
const url = new URL(location.href);
update_url(url);
}
}
});

Expand Down Expand Up @@ -1702,6 +1708,15 @@ export function create_client(app, target) {
stores.navigating.set(null);
}
});

/**
* @param {URL} url
*/
function update_url(url) {
current.url = url;
stores.page.set({ ...page, url });
stores.page.notify();
}
},

_hydrate: async ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

<div id="store-data">{JSON.stringify($page.data)}</div>
<div id="store-error">{$page.error?.message}</div>
<div id="url-hash">{$page.url.hash}</div>

<nav>
<a href="/store/data/xxx">xxx</a> <a href="/store/data/yyy">yyy</a>
Expand Down
24 changes: 24 additions & 0 deletions packages/kit/test/apps/basics/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,30 @@ test.describe('$app/stores', () => {
expect(await page.textContent('#nav-status')).toBe('not currently navigating');
}
});

test('should update page store when URL hash is changed through the address bar', async ({
baseURL,
page,
javaScriptEnabled
}) => {
const href = `${baseURL}/store/data/zzz`;
await page.goto(href);

expect(await page.textContent('#url-hash')).toBe('');

if (javaScriptEnabled) {
for (const urlHash of ['#1', '#2', '#5', '#8']) {
await page.evaluate(
({ href, urlHash }) => {
location.href = `${href}${urlHash}`;
},
{ href, urlHash }
);

expect(await page.textContent('#url-hash')).toBe(urlHash);
}
}
});
});

test.describe('searchParams', () => {
Expand Down

0 comments on commit 4d7f38f

Please sign in to comment.