Repository: sveltejs/kit (js)

Issue:
warning printed to console
### Describe the bug

Loading the page in a new app gives:

>client.js?t=1669422529721&v=a06a7a43:1388 [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952

### Reproduction

```
npm create svelte@latest myapp
```

### Logs

_No response_

### System Info

```Shell
1.0.0-next.561
```


### Severity

annoyance

### Additional Information

_No response_

Pull request:
make touchstart listener passive
closes #7813

### 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.
- [ ] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [ ] 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/calm-peaches-enjoy.md b/.changeset/calm-peaches-enjoy.md
new file mode 100644
index 000000000..aafb78f21
--- /dev/null
+++ b/.changeset/calm-peaches-enjoy.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+[fix] handle redirects in handle hook while processing data request
diff --git a/.changeset/chilled-drinks-hug.md b/.changeset/chilled-drinks-hug.md
new file mode 100644
index 000000000..a7a2d220a
--- /dev/null
+++ b/.changeset/chilled-drinks-hug.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Make touchstart listener passive
diff --git a/.changeset/grumpy-maps-complain.md b/.changeset/grumpy-maps-complain.md
new file mode 100644
index 000000000..72100d146
--- /dev/null
+++ b/.changeset/grumpy-maps-complain.md
@@ -0,0 +1,5 @@
+---
+"@sveltejs/kit": patch
+---
+
+[breaking] remove `getStaticDirectory()` from builder API
diff --git a/packages/kit/src/core/adapt/builder.js b/packages/kit/src/core/adapt/builder.js
index 39f78fda3..e9e0dbf71 100644
--- a/packages/kit/src/core/adapt/builder.js
+++ b/packages/kit/src/core/adapt/builder.js
@@ -126,10 +126,6 @@ export function create_builder({ config, build_data, routes, prerendered, log })
 			return `${config.kit.outDir}/output/server`;
 		},
 
-		getStaticDirectory() {
-			return config.kit.files.assets;
-		},
-
 		getAppPath() {
 			return build_data.app_path;
 		},
diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js
index 7d05d6490..4aa7378fb 100644
--- a/packages/kit/src/runtime/client/client.js
+++ b/packages/kit/src/runtime/client/client.js
@@ -1385,7 +1385,7 @@ export function create_client({ target, base }) {
 				}, 20);
 			};
 
-			target.addEventListener('touchstart', trigger_prefetch);
+			target.addEventListener('touchstart', trigger_prefetch, { passive: true });
 			target.addEventListener('mousemove', handle_mousemove);
 			target.addEventListener('sveltekit:trigger_prefetch', trigger_prefetch);
 
diff --git a/packages/kit/src/runtime/server/data/index.js b/packages/kit/src/runtime/server/data/index.js
index 44a0fe296..3b0f7e97c 100644
--- a/packages/kit/src/runtime/server/data/index.js
+++ b/packages/kit/src/runtime/server/data/index.js
@@ -117,12 +117,7 @@ export async function render_data(event, route, options, state, trailing_slash)
 		const error = normalize_error(e);
 
 		if (error instanceof Redirect) {
-			return json_response(
-				JSON.stringify({
-					type: 'redirect',
-					location: error.location
-				})
-			);
+			return redirect_json_response(error);
 		} else {
 			// TODO make it clearer that this was an unexpected error
 			return json_response(JSON.stringify(handle_error_and_jsonify(event, options, error)));
@@ -143,3 +138,15 @@ function json_response(json, status = 200) {
 		}
 	});
 }
+
+/**
+ * @param {Redirect} redirect
+ */
+export function redirect_json_response(redirect) {
+	return json_response(
+		JSON.stringify({
+			type: 'redirect',
+			location: redirect.location
+		})
+	);
+}
diff --git a/packages/kit/src/runtime/server/index.js b/packages/kit/src/runtime/server/index.js
index f5554c4c6..4b9119258 100644
--- a/packages/kit/src/runtime/server/index.js
+++ b/packages/kit/src/runtime/server/index.js
@@ -13,7 +13,7 @@ import {
 	strip_data_suffix
 } from '../../utils/url.js';
 import { exec } from '../../utils/routing.js';
-import { INVALIDATED_HEADER, render_data } from './data/index.js';
+import { INVALIDATED_HEADER, redirect_json_response, render_data } from './data/index.js';
 import { add_cookies_to_headers, get_cookies } from './cookie.js';
 import { create_fetch } from './fetch.js';
 import { Redirect } from '../control.js';
@@ -289,10 +289,23 @@ export async function respond(request, options, state) {
 			}
 		}
 
+		// Edge case: If user does `return Response(30x)` in handle hook while processing a data request,
+		// we need to transform the redirect response to a corresponding JSON response.
+		if (is_data_request && response.status >= 300 && response.status <= 308) {
+			const location = response.headers.get('location');
+			if (location) {
+				return redirect_json_response(new Redirect(/** @type {any} */ (response.status), location));
+			}
+		}
+
 		return response;
 	} catch (error) {
 		if (error instanceof Redirect) {
-			return redirect_response(error.status, error.location);
+			if (is_data_request) {
+				return redirect_json_response(error);
+			} else {
+				return redirect_response(error.status, error.location);
+			}
 		}
 		return handle_fatal_error(event, options, error);
 	}
diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts
index cdfe21595..ea7672e19 100644
--- a/packages/kit/types/index.d.ts
+++ b/packages/kit/types/index.d.ts
@@ -77,7 +77,6 @@ export interface Builder {
 	getBuildDirectory(name: string): string;
 	getClientDirectory(): string;
 	getServerDirectory(): string;
-	getStaticDirectory(): string;
 	/** The application path including any configured base path */
 	getAppPath(): string;
 


Test patch:
diff --git a/packages/kit/test/apps/basics/src/hooks.server.js b/packages/kit/test/apps/basics/src/hooks.server.js
index d7541ef1d..2e5938aa5 100644
--- a/packages/kit/test/apps/basics/src/hooks.server.js
+++ b/packages/kit/test/apps/basics/src/hooks.server.js
@@ -1,7 +1,7 @@
 import fs from 'fs';
 import { sequence } from '@sveltejs/kit/hooks';
 import { HttpError } from '../../../../src/runtime/control';
-import { error } from '@sveltejs/kit';
+import { error, redirect } from '@sveltejs/kit';
 
 /**
  * Transform an error into a POJO, by copying its `name`, `message`
@@ -80,6 +80,17 @@ export const handle = sequence(
 		} catch {}
 
 		return response;
+	},
+	async ({ event, resolve }) => {
+		if (event.url.pathname.includes('/redirect/in-handle')) {
+			if (event.url.search === '?throw') {
+				throw redirect(307, event.url.origin + '/redirect/c');
+			} else {
+				return new Response(undefined, { status: 307, headers: { location: '/redirect/c' } });
+			}
+		}
+
+		return resolve(event);
 	}
 );
 
diff --git a/packages/kit/test/apps/basics/src/routes/redirect/+page.svelte b/packages/kit/test/apps/basics/src/routes/redirect/+page.svelte
index 70f0a624f..852940e4e 100644
--- a/packages/kit/test/apps/basics/src/routes/redirect/+page.svelte
+++ b/packages/kit/test/apps/basics/src/routes/redirect/+page.svelte
@@ -7,3 +7,6 @@
 
 <a href="/redirect/missing-status/a">a (missing-status)</a>
 <a href="/redirect/missing-status/b">b (missing-status)</a>
+
+<a href="/redirect/in-handle?throw">in-handle (throw redirect)</a>
+<a href="/redirect/in-handle?response">in-handle (return Response)</a>
diff --git a/packages/kit/test/apps/basics/src/routes/redirect/in-handle/+page.server.js b/packages/kit/test/apps/basics/src/routes/redirect/in-handle/+page.server.js
new file mode 100644
index 000000000..23addb029
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/redirect/in-handle/+page.server.js
@@ -0,0 +1,1 @@
+export function load() {}
diff --git a/packages/kit/test/apps/basics/src/routes/redirect/in-handle/+page.svelte b/packages/kit/test/apps/basics/src/routes/redirect/in-handle/+page.svelte
new file mode 100644
index 000000000..6a72cbc95
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/redirect/in-handle/+page.svelte
@@ -0,0 +1,1 @@
+<h1>in-handle</h1>
diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js
index 8678d1b1a..633ea3b7a 100644
--- a/packages/kit/test/apps/basics/test/test.js
+++ b/packages/kit/test/apps/basics/test/test.js
@@ -1337,6 +1337,32 @@ test.describe('Redirects', () => {
 			expect(await page.textContent('h1')).toBe('Hazaa!');
 		}
 	});
+
+	test('redirect response in handle hook', async ({ baseURL, clicknav, page }) => {
+		await page.goto('/redirect');
+
+		await clicknav('[href="/redirect/in-handle?response"]');
+
+		await page.waitForURL('/redirect/c');
+		expect(await page.textContent('h1')).toBe('c');
+		expect(page.url()).toBe(`${baseURL}/redirect/c`);
+
+		await page.goBack();
+		expect(page.url()).toBe(`${baseURL}/redirect`);
+	});
+
+	test('throw redirect in handle hook', async ({ baseURL, clicknav, page }) => {
+		await page.goto('/redirect');
+
+		await clicknav('[href="/redirect/in-handle?throw"]');
+
+		await page.waitForURL('/redirect/c');
+		expect(await page.textContent('h1')).toBe('c');
+		expect(page.url()).toBe(`${baseURL}/redirect/c`);
+
+		await page.goBack();
+		expect(page.url()).toBe(`${baseURL}/redirect`);
+	});
 });
 
 test.describe('Routing', () => {