Repository: sveltejs/kit (js)

Issue:
Can't `location.assign(url)` in `load()` function: throws `Illegal invocation`
### Describe the bug

I have a fallthrough route, which I want to _always be server-rendered_. The use-case is that we're migrating from Angular to SvelteKit, and any pages which SvelteKit doesn't recognise should:
- if invoked client-side, reload the URL to force a SSR
- return a page which boots AngularJS, with no hydration or SvelteKit router
- this ensures that only AngularJS is running in the browser, as SvelteKit will not send any of its own JS with the SSR response

The fix for [this issue](https://github.com/sveltejs/kit/issues/4788) (PR [here](https://github.com/sveltejs/kit/pull/4983)) introduced a `Proxy` wrapper for the `url` input parameter to the `load()` function. This now causes my browser-side interceptor code to throw a `TypeError: Illegal invocation`.


### Reproduction

Click the link to the fallthrough page in this repro: https://stackblitz.com/edit/sveltejs-kit-template-default-cn2bpx?file=src%2Froutes%2F[...fallthrough].svelte&terminal=dev, and you'll see:

```
500
Illegal invocation
TypeError: Illegal invocation
    at load (https://sveltejs-kit-template-default-cn2bpx--3000.local.webcontainer.io/src/routes/[...fallthrough].svelte?t=1653555167052:81:12)
    at load_node (https://sveltejs-kit-template-default-cn2bpx--3000.local.webcontainer.io/@fs/home/projects/sveltejs-kit-template-default-cn2bpx/.svelte-kit/runtime/client/start.js:1029:33)
    at load_route (https://sveltejs-kit-template-default-cn2bpx--3000.local.webcontainer.io/@fs/home/projects/sveltejs-kit-template-default-cn2bpx/.svelte-kit/runtime/client/start.js:1147:20)
    at async update (https://sveltejs-kit-template-default-cn2bpx--3000.local.webcontainer.io/@fs/home/projects/sveltejs-kit-template-default-cn2bpx/.svelte-kit/runtime/client/start.js:626:38)
    at async navigate (https://sveltejs-kit-template-default-cn2bpx--3000.local.webcontainer.io/@fs/home/projects/sveltejs-kit-template-default-cn2bpx/.svelte-kit/runtime/client/start.js:1372:3)
```

Change the `location.assign(url)` to `location.assign(url.href)` and it works fine.

### Logs

_No response_

### System Info

```shell
`@sveltejs/kit@1.0.0-next.345`
```


### Severity

serious, but I can work around it

### Additional Information

This may purely be a documentation/education thing. The [docs say](https://kit.svelte.dev/docs/loading#input-url) **`url` is an instance of [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL)**, but that's not entirely true, as the implicit casting to string with `location.assign(url)` is broken by the Proxy wrapper. Either we should document that limitation, or, if possible, improve the Proxy with a `toString()` method or whatever is required.

Pull request:
fix: URL instance methods work in `load`
Fixes #5083.

This is the "surgical approach" -- just replace the `hash` property with a custom getter. The other option is (if we're really committed to using a Proxy):

```typescript
new Proxy(url, {
    get: (target, property, receiver) => {
        if (property === 'hash') {
            throw new Error(
                'url.hash is inaccessible from load. Consider accessing hash from the page store within the script tag of your component.'
            );
        }

        if (!(property in target)) {
          return undefined;
        }
        const value = target[property];
        return typeof value === "function"
          ? (...args) => value.apply(target, args)
          : value;
    }
});
```

This scares me a little bit, because it's a lot harder to anticipate what other side effects it might exhibit. 

### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [x] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. All changesets should be `patch` until SvelteKit 1.0


Patch:
diff --git a/.changeset/hip-kangaroos-check.md b/.changeset/hip-kangaroos-check.md
new file mode 100644
index 000000000..f76354dbf
--- /dev/null
+++ b/.changeset/hip-kangaroos-check.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/adapter-cloudflare-workers': patch
+---
+
+Simplify example wrangler.toml, and fix outdated README
diff --git a/.changeset/popular-pets-obey.md b/.changeset/popular-pets-obey.md
new file mode 100644
index 000000000..12223bb24
--- /dev/null
+++ b/.changeset/popular-pets-obey.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+[fix] URL instance methods now work in `load`
diff --git a/documentation/docs/02-routing.md b/documentation/docs/02-routing.md
index 1b2dbdb2f..d4bf789c4 100644
--- a/documentation/docs/02-routing.md
+++ b/documentation/docs/02-routing.md
@@ -100,7 +100,7 @@ The job of a [request handler](/docs/types#sveltejs-kit-requesthandler) is to re
 
 #### Page endpoints
 
-If an endpoint has the same filename as a page (except for the extension), the page gets its props from the endpoint — via `fetch` during client-side navigation, or via direct function call during SSR.
+If an endpoint has the same filename as a page (except for the extension), the page gets its props from the endpoint — via `fetch` during client-side navigation, or via direct function call during SSR. If a page uses syntax for [named layouts](/docs/layouts#named-layouts) or [matchers](/docs/routing#advanced-routing-matching) in its filename then the corresponding page endpoint's filename must also include them.
 
 A page like `src/routes/items/[id].svelte` could get its props from the `body` in the endpoint above:
 
diff --git a/documentation/docs/04-loading.md b/documentation/docs/04-loading.md
index 5ca73068d..d81672f20 100644
--- a/documentation/docs/04-loading.md
+++ b/documentation/docs/04-loading.md
@@ -26,7 +26,7 @@ If the data for a page comes from its endpoint, you may not need a `load` functi
 
 > Note the `<script context="module">` — this is necessary because `load` runs before the component is rendered. Code that is per-component instance should go into a second `<script>` tag.
 
-As with [endpoints](/docs/routing#endpoints), pages can import [generated types](/docs/types#generated) — the `./[slug]` in the example above — to ensure that `params` are correctly typed.
+As with [endpoints](/docs/routing#endpoints), pages can import [generated types](/docs/types#generated-types) — the `./[slug]` in the example above — to ensure that `params` are correctly typed.
 
 `load` is similar to `getStaticProps` or `getServerSideProps` in Next.js, except that `load` runs on both the server and the client. In the example above, if a user clicks on a link to this page the data will be fetched from `cms.example.com` without going via our server.
 
diff --git a/documentation/faq/65-read-package-json.md b/documentation/faq/65-read-package-json.md
index 0bce2e7f4..25a591993 100644
--- a/documentation/faq/65-read-package-json.md
+++ b/documentation/faq/65-read-package-json.md
@@ -1,5 +1,5 @@
 ---
-title: How do I include details from `package.json` in my application?
+title: How do I include details from package.json in my application?
 ---
 
 You cannot directly require JSON files, since SvelteKit expects [`svelte.config.js`](/docs/configuration) to be an ES module. If you'd like to include your application's version number or other information from `package.json` in your application, you can load JSON like so:
diff --git a/package.json b/package.json
index 43db41151..96de77919 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,7 @@
 		"turbo": "^1.2.14",
 		"typescript": "^4.7.2"
 	},
-	"packageManager": "pnpm@7.1.9",
+	"packageManager": "pnpm@7.3.0",
 	"engines": {
 		"pnpm": "^7.0.0"
 	},
diff --git a/packages/adapter-cloudflare-workers/README.md b/packages/adapter-cloudflare-workers/README.md
index 3ccda6387..6d77a06ef 100644
--- a/packages/adapter-cloudflare-workers/README.md
+++ b/packages/adapter-cloudflare-workers/README.md
@@ -33,62 +33,42 @@ export default {
 
 ## Basic Configuration
 
-**You will need [Wrangler](https://developers.cloudflare.com/workers/cli-wrangler/install-update) installed on your system**
-
-This adapter expects to find a [wrangler.toml](https://developers.cloudflare.com/workers/platform/sites/configuration) file in the project root. It will determine where to write static assets and the worker based on the `site.bucket` and `site.entry-point` settings.
-
-Generate this file using `wrangler` from your project directory
-
-```sh
-wrangler init --site my-site-name
-```
-
-Now you should get some details from Cloudflare. You should get your:
-
-1. Account ID
-2. And your Zone-ID (Optional)
-
-Get them by visiting your [Cloudflare dashboard](https://dash.cloudflare.com) and click on any domain. There, you can scroll down and on the left, you can see your details under **API**.
-
-Then configure your sites build directory and your account-details in the config file:
+This adapter expects to find a [wrangler.toml](https://developers.cloudflare.com/workers/platform/sites/configuration) file in the project root. It should look something like this:
 
 ```toml
-account_id = 'YOUR ACCOUNT_ID'
-zone_id    = 'YOUR ZONE_ID' # optional, if you don't specify this a workers.dev subdomain will be used.
+name = "<your-service-name>"
+account_id = "<your-account-id>"
+
+main = "./.cloudflare/worker.js"
+site.bucket = "./.cloudflare/public"
 
-type = "javascript"
+build.command = "npm run build"
 
-[build]
-# Assume it's already been built. You can make this "npm run build" to ensure a build before publishing
-command = ""
+compatibility_date = "2021-11-12"
+workers_dev = true
+```
 
-[build.upload]
-format = "modules"
-main = "./worker.mjs"
+`<your-service-name>` can be anything. `<your-account-id>` can be found by logging into your [Cloudflare dashboard](https://dash.cloudflare.com) and grabbing it from the end of the URL:
 
-[site]
-bucket = "./.cloudflare/assets"
-entry-point = "./.cloudflare/worker"
+```
+https://dash.cloudflare.com/<your-account-id>
 ```
 
-It's recommended that you add the `build` and `workers-site` folders (or whichever other folders you specify) to your `.gitignore`.
+> It's recommended that you add the `.cloudflare` directory (or whichever directories you specified for `main` and `site.bucket`) to your `.gitignore`.
 
-Now, log in with wrangler:
+You will need to install [wrangler](https://developers.cloudflare.com/workers/wrangler/get-started/) and log in, if you haven't already:
 
-```sh
+```
+npm i -g wrangler
 wrangler login
 ```
 
-Build your project and publish it:
+Then, you can build your app and deploy it:
 
 ```sh
-npm run build && wrangler publish
+wrangler publish
 ```
 
-**You are done!**
-
-More info on configuring a cloudflare worker site can be found [here](https://developers.cloudflare.com/workers/platform/sites/start-from-existing)
-
 ## Changelog
 
 [The Changelog for this package is available on GitHub](https://github.com/sveltejs/kit/blob/master/packages/adapter-cloudflare-workers/CHANGELOG.md).
diff --git a/packages/adapter-cloudflare-workers/index.js b/packages/adapter-cloudflare-workers/index.js
index cb822fdad..b40ee8c66 100644
--- a/packages/adapter-cloudflare-workers/index.js
+++ b/packages/adapter-cloudflare-workers/index.js
@@ -116,7 +116,6 @@ function validate_config(builder) {
 
 		name = "<your-site-name>"
 		account_id = "<your-account-id>"
-		route = "<your-route>"
 
 		main = "./.cloudflare/worker.js"
 		site.bucket = "./.cloudflare/public"
diff --git a/packages/adapter-vercel/package.json b/packages/adapter-vercel/package.json
index 6bacb9cf9..c65cc2b72 100644
--- a/packages/adapter-vercel/package.json
+++ b/packages/adapter-vercel/package.json
@@ -29,7 +29,7 @@
 		"check": "tsc"
 	},
 	"dependencies": {
-		"@vercel/nft": "^0.19.1",
+		"@vercel/nft": "^0.20.0",
 		"esbuild": "^0.14.42"
 	},
 	"devDependencies": {
diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js
index ddc5c329c..e098ab428 100644
--- a/packages/kit/src/runtime/client/client.js
+++ b/packages/kit/src/runtime/client/client.js
@@ -2,7 +2,7 @@ import { onMount, tick } from 'svelte';
 import { writable } from 'svelte/store';
 import { coalesce_to_error } from '../../utils/error.js';
 import { normalize } from '../load.js';
-import { normalize_path } from '../../utils/url.js';
+import { LoadURL, normalize_path } from '../../utils/url.js';
 import {
 	create_updated_store,
 	find_anchor,
@@ -527,6 +527,7 @@ export function create_client({ target, session, base, trailing_slash }) {
 		}
 
 		const session = $session;
+		const load_url = new LoadURL(url);
 
 		if (module.load) {
 			/** @type {import('types').LoadEvent} */
@@ -536,18 +537,7 @@ export function create_client({ target, session, base, trailing_slash }) {
 				props: props || {},
 				get url() {
 					node.uses.url = true;
-
-					return new Proxy(url, {
-						get: (target, property) => {
-							if (property === 'hash') {
-								throw new Error(
-									'url.hash is inaccessible from load. Consider accessing hash from the page store within the script tag of your component.'
-								);
-							}
-
-							return Reflect.get(target, property, target);
-						}
-					});
+					return load_url;
 				},
 				get session() {
 					node.uses.session = true;
diff --git a/packages/kit/src/runtime/server/page/load_node.js b/packages/kit/src/runtime/server/page/load_node.js
index 37c700070..4b0c54cc7 100644
--- a/packages/kit/src/runtime/server/page/load_node.js
+++ b/packages/kit/src/runtime/server/page/load_node.js
@@ -4,6 +4,7 @@ import { normalize } from '../../load.js';
 import { respond } from '../index.js';
 import { is_root_relative, resolve } from '../../../utils/url.js';
 import { create_prerendering_url_proxy } from './utils.js';
+import { LoadURL } from '../../../utils/url.js';
 import { is_pojo, lowercase_keys, normalize_request_method } from '../utils.js';
 import { coalesce_to_error } from '../../../utils/error.js';
 import { domain_matches, path_matches } from './cookie.js';
@@ -84,7 +85,7 @@ export async function load_node({
 	} else if (module.load) {
 		/** @type {import('types').LoadEvent} */
 		const load_input = {
-			url: state.prerendering ? create_prerendering_url_proxy(event.url) : event.url,
+			url: state.prerendering ? create_prerendering_url_proxy(event.url) : new LoadURL(event.url),
 			params: event.params,
 			props: shadow.body || {},
 			routeId: event.routeId,
diff --git a/packages/kit/src/utils/url.js b/packages/kit/src/utils/url.js
index 808cacd92..61a7d79ee 100644
--- a/packages/kit/src/utils/url.js
+++ b/packages/kit/src/utils/url.js
@@ -52,3 +52,12 @@ export function normalize_path(path, trailing_slash) {
 
 	return path;
 }
+
+export class LoadURL extends URL {
+	/** @returns {string} */
+	get hash() {
+		throw new Error(
+			'url.hash is inaccessible from load. Consider accessing hash from the page store within the script tag of your component.'
+		);
+	}
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0896007f8..4f070644e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -182,11 +182,11 @@ importers:
     specifiers:
       '@sveltejs/kit': workspace:*
       '@types/node': ^16.11.36
-      '@vercel/nft': ^0.19.1
+      '@vercel/nft': ^0.20.0
       esbuild: ^0.14.42
       typescript: ^4.7.2
     dependencies:
-      '@vercel/nft': 0.19.1
+      '@vercel/nft': 0.20.0
       esbuild: 0.14.42
     devDependencies:
       '@sveltejs/kit': link:../kit
@@ -1303,8 +1303,8 @@ packages:
       - supports-color
     dev: true
 
-  /@vercel/nft/0.19.1:
-    resolution: {integrity: sha512-klR5oN7S3WJsZz0r6Xsq7o8YlFEyU3/00VmlpZzIPVFzKfbcEjXo/sVR5lQBUqNKuOzhcbxaFtzW9aOyHjmPYA==}
+  /@vercel/nft/0.20.0:
+    resolution: {integrity: sha512-+lxsJP/sG4E8UkhfrJC6evkLLfUpZrjXxqEdunr3Q9kiECi8JYBGz6B5EpU1+MmeNnRoSphLcLh/1tI998ye4w==}
     hasBin: true
     dependencies:
       '@mapbox/node-pre-gyp': 1.0.9
@@ -3740,7 +3740,7 @@ packages:
     dev: false
 
   /number-is-nan/1.0.1:
-    resolution: {integrity: sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=}
+    resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==}
     engines: {node: '>=0.10.0'}
 
   /object-assign/4.1.1:
@@ -3804,7 +3804,7 @@ packages:
     dev: true
 
   /os-homedir/1.0.2:
-    resolution: {integrity: sha1-/7xJiDNuDoM94MFox+8VISGqf7M=}
+    resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==}
     engines: {node: '>=0.10.0'}
     dev: false
 
@@ -3818,7 +3818,7 @@ packages:
     dev: true
 
   /os-tmpdir/1.0.2:
-    resolution: {integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=}
+    resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
     engines: {node: '>=0.10.0'}
 
   /osenv/0.1.5:
@@ -4593,7 +4593,7 @@ packages:
     dev: true
 
   /string-width/1.0.2:
-    resolution: {integrity: sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=}
+    resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==}
     engines: {node: '>=0.10.0'}
     dependencies:
       code-point-at: 1.1.0
@@ -4643,7 +4643,7 @@ packages:
       safe-buffer: 5.2.1
 
   /strip-ansi/3.0.1:
-    resolution: {integrity: sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=}
+    resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==}
     engines: {node: '>=0.10.0'}
     dependencies:
       ansi-regex: 2.1.1
@@ -4679,7 +4679,7 @@ packages:
     dev: true
 
   /strip-json-comments/2.0.1:
-    resolution: {integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo=}
+    resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
     engines: {node: '>=0.10.0'}
 
   /strip-json-comments/3.1.1:
@@ -5360,7 +5360,7 @@ packages:
   /wide-align/1.1.5:
     resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
     dependencies:
-      string-width: 1.0.2
+      string-width: 4.2.3
 
   /word-wrap/1.2.3:
     resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==}
diff --git a/sites/kit.svelte.dev/src/lib/search/Search.svelte b/sites/kit.svelte.dev/src/lib/search/Search.svelte
index e5de0cb55..07a384352 100644
--- a/sites/kit.svelte.dev/src/lib/search/Search.svelte
+++ b/sites/kit.svelte.dev/src/lib/search/Search.svelte
@@ -15,7 +15,7 @@
 			e.target.value = '';
 		}}
 		on:mousedown|preventDefault={() => ($searching = true)}
-		on:touchstart|preventDefault={() => ($searching = true)}
+		on:touchend|preventDefault={() => ($searching = true)}
 		type="search"
 		name="q"
 		placeholder="Search"
diff --git a/sites/kit.svelte.dev/src/routes/faq/index.svelte b/sites/kit.svelte.dev/src/routes/faq/index.svelte
index a2c264c02..0cb5b5f02 100644
--- a/sites/kit.svelte.dev/src/routes/faq/index.svelte
+++ b/sites/kit.svelte.dev/src/routes/faq/index.svelte
@@ -2,6 +2,7 @@
 	import { Permalink } from '@sveltejs/site-kit';
 	import '$lib/docs/client/docs.css';
 	import '$lib/docs/client/shiki.css';
+	import '@sveltejs/site-kit/code.css';
 	import * as hovers from '$lib/docs/client/hovers.js';
 
 	export let sections;
@@ -79,8 +80,8 @@
 	}
 
 	h2 {
-		margin: -4rem 0 1rem 0;
-		padding-top: 10rem;
+		margin: 0rem 0 1rem 0;
+		padding-top: 6rem;
 		padding-bottom: 0.2rem;
 		color: var(--text);
 		/* max-width: 24em; */


Test patch:
diff --git a/packages/adapter-static/test/test.js b/packages/adapter-static/test/test.js
index 0665df152..93bbd1e97 100644
--- a/packages/adapter-static/test/test.js
+++ b/packages/adapter-static/test/test.js
@@ -34,8 +34,7 @@ run('spa', (test) => {
 	test('renders error page for missing page', async ({ base, page }) => {
 		await page.goto(`${base}/nosuchpage`);
 		assert.equal(await page.textContent('h1'), '404');
-		assert.equal(await page.textContent('h2'), 'count: 1');
-
 		await page.waitForLoadState('networkidle', { timeout: 1000 });
+		assert.equal(await page.textContent('h2'), 'count: 1');
 	});
 });
diff --git a/packages/kit/test/apps/basics/src/routes/load/url-to-string.svelte b/packages/kit/test/apps/basics/src/routes/load/url-to-string.svelte
new file mode 100644
index 000000000..122dad20b
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/load/url-to-string.svelte
@@ -0,0 +1,8 @@
+<script context="module">
+	export const load = ({ url }) => {
+		url.toString();
+		return {};
+	};
+</script>
+
+<h1>I didn't break!</h1>
diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js
index cb159068c..60611a417 100644
--- a/packages/kit/test/apps/basics/test/test.js
+++ b/packages/kit/test/apps/basics/test/test.js
@@ -1516,6 +1516,13 @@ test.describe.parallel('Load', () => {
 		}
 	});
 
+	test('url instance methods work in load', async ({ page, javaScriptEnabled }) => {
+		if (javaScriptEnabled) {
+			await page.goto('/load/url-to-string');
+			expect(await page.textContent('h1')).toBe("I didn't break!");
+		}
+	});
+
 	test('using window.fetch causes a warning', async ({ page, javaScriptEnabled }) => {
 		if (javaScriptEnabled && process.env.DEV) {
 			const warnings = [];
@@ -1863,9 +1870,9 @@ test.describe.parallel('$app/stores', () => {
 		expect(await page.textContent('#nav-status')).toBe('not currently navigating');
 
 		if (javaScriptEnabled) {
-			page.click('a[href="/store/navigating/c"]');
+			await page.click('a[href="/store/navigating/c"]');
 			await page.waitForTimeout(100); // gross, but necessary since no navigation occurs
-			page.click('a[href="/store/navigating/a"]');
+			await page.click('a[href="/store/navigating/a"]');
 
 			await page.waitForSelector('#not-navigating', { timeout: 500 });
 			expect(await page.textContent('#nav-status')).toBe('not currently navigating');
@@ -2218,6 +2225,7 @@ test.describe.parallel('Routing', () => {
 	test('does not attempt client-side navigation to server routes', async ({ page }) => {
 		await page.goto('/routing');
 		await page.click('[href="/routing/ambiguous/ok.json"]');
+		await page.waitForLoadState('networkidle');
 		expect(await page.textContent('body')).toBe('ok');
 	});