@sveltejs/kit 2.50.2 → 2.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/core/sync/write_tsconfig.js +7 -5
- package/src/exports/public.d.ts +14 -1
- package/src/exports/vite/index.js +2 -4
- package/src/exports/vite/static_analysis/utils.js +17 -0
- package/src/runtime/client/client.js +22 -19
- package/src/runtime/server/fetch.js +6 -2
- package/src/runtime/server/page/csp.js +54 -22
- package/src/runtime/server/page/index.js +7 -2
- package/src/runtime/server/page/render.js +104 -43
- package/src/types/internal.d.ts +8 -4
- package/src/version.js +1 -1
- package/types/index.d.ts +19 -2
- package/types/index.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.51.0",
|
|
4
4
|
"description": "SvelteKit is the fastest way to build Svelte apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@opentelemetry/api": "^1.0.0",
|
|
37
|
-
"@playwright/test": "1.
|
|
37
|
+
"@playwright/test": "1.58.2",
|
|
38
38
|
"@sveltejs/vite-plugin-svelte": "^6.0.0-next.3",
|
|
39
39
|
"@types/connect": "^3.4.38",
|
|
40
40
|
"@types/node": "^18.19.119",
|
|
@@ -62,10 +62,8 @@ export function get_tsconfig(kit) {
|
|
|
62
62
|
config_relative('vite.config.js'),
|
|
63
63
|
config_relative('vite.config.ts')
|
|
64
64
|
]);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const src_includes = [kit.files.routes, kit.files.lib, path.resolve('src')].filter((dir) => {
|
|
68
|
-
const relative = path.relative(path.resolve('src'), dir);
|
|
65
|
+
const src_includes = [kit.files.routes, kit.files.lib, kit.files.src].filter((dir) => {
|
|
66
|
+
const relative = path.relative(kit.files.src, dir);
|
|
69
67
|
return !relative || relative.startsWith('..');
|
|
70
68
|
});
|
|
71
69
|
for (const dir of src_includes) {
|
|
@@ -76,10 +74,14 @@ export function get_tsconfig(kit) {
|
|
|
76
74
|
|
|
77
75
|
// Test folder is a special case - we advocate putting tests in a top-level test folder
|
|
78
76
|
// and it's not configurable (should we make it?)
|
|
79
|
-
const test_folder = project_relative('
|
|
77
|
+
const test_folder = project_relative('test');
|
|
80
78
|
include.add(config_relative(`${test_folder}/**/*.js`));
|
|
81
79
|
include.add(config_relative(`${test_folder}/**/*.ts`));
|
|
82
80
|
include.add(config_relative(`${test_folder}/**/*.svelte`));
|
|
81
|
+
const tests_folder = project_relative('tests');
|
|
82
|
+
include.add(config_relative(`${tests_folder}/**/*.js`));
|
|
83
|
+
include.add(config_relative(`${tests_folder}/**/*.ts`));
|
|
84
|
+
include.add(config_relative(`${tests_folder}/**/*.svelte`));
|
|
83
85
|
|
|
84
86
|
const exclude = [config_relative('node_modules/**')];
|
|
85
87
|
// Add service worker to exclude list so that worker types references in it don't spill over into the rest of the app
|
package/src/exports/public.d.ts
CHANGED
|
@@ -1200,6 +1200,19 @@ export interface NavigationTarget<
|
|
|
1200
1200
|
* The URL that is navigated to
|
|
1201
1201
|
*/
|
|
1202
1202
|
url: URL;
|
|
1203
|
+
/**
|
|
1204
|
+
* The scroll position associated with this navigation.
|
|
1205
|
+
*
|
|
1206
|
+
* For the `from` target, this is the scroll position at the moment of navigation.
|
|
1207
|
+
*
|
|
1208
|
+
* For the `to` target, this represents the scroll position that will be or was restored:
|
|
1209
|
+
* - In `beforeNavigate` and `onNavigate`, this is only available for `popstate` navigations (back/forward button)
|
|
1210
|
+
* and will be `null` for other navigation types, since the final scroll position isn't known
|
|
1211
|
+
* ahead of time.
|
|
1212
|
+
* - In `afterNavigate`, this is always the scroll position that was applied after the navigation
|
|
1213
|
+
* completed.
|
|
1214
|
+
*/
|
|
1215
|
+
scroll: { x: number; y: number } | null;
|
|
1203
1216
|
}
|
|
1204
1217
|
|
|
1205
1218
|
/**
|
|
@@ -1249,7 +1262,7 @@ export interface NavigationEnter extends NavigationBase {
|
|
|
1249
1262
|
delta?: undefined;
|
|
1250
1263
|
|
|
1251
1264
|
/**
|
|
1252
|
-
* Dispatched `Event` object when navigation
|
|
1265
|
+
* Dispatched `Event` object when navigation occurred by `popstate` or `link`.
|
|
1253
1266
|
*/
|
|
1254
1267
|
event?: undefined;
|
|
1255
1268
|
}
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
} from './module_ids.js';
|
|
41
41
|
import { import_peer } from '../../utils/import.js';
|
|
42
42
|
import { compact } from '../../utils/array.js';
|
|
43
|
-
import { should_ignore } from './static_analysis/utils.js';
|
|
43
|
+
import { should_ignore, has_children } from './static_analysis/utils.js';
|
|
44
44
|
|
|
45
45
|
const cwd = posixify(process.cwd());
|
|
46
46
|
|
|
@@ -112,10 +112,8 @@ const warning_preprocessor = {
|
|
|
112
112
|
if (!filename) return;
|
|
113
113
|
|
|
114
114
|
const basename = path.basename(filename);
|
|
115
|
-
const has_children =
|
|
116
|
-
content.includes('<slot') || (isSvelte5Plus() && content.includes('{@render'));
|
|
117
115
|
|
|
118
|
-
if (basename.startsWith('+layout.') && !has_children) {
|
|
116
|
+
if (basename.startsWith('+layout.') && !has_children(content, isSvelte5Plus())) {
|
|
119
117
|
const message =
|
|
120
118
|
`\n${colors.bold().red(path.relative('.', filename))}\n` +
|
|
121
119
|
`\`<slot />\`${isSvelte5Plus() ? ' or `{@render ...}` tag' : ''}` +
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if content has children rendering (slot, @render, or children prop forwarding)
|
|
3
|
+
* @param {string} content - The markup content
|
|
4
|
+
* @param {boolean} is_svelte_5_plus - Whether the project uses Svelte 5+
|
|
5
|
+
* @returns {boolean}
|
|
6
|
+
*/
|
|
7
|
+
export function has_children(content, is_svelte_5_plus) {
|
|
8
|
+
return (
|
|
9
|
+
content.includes('<slot') ||
|
|
10
|
+
(is_svelte_5_plus &&
|
|
11
|
+
(content.includes('{@render') ||
|
|
12
|
+
// children may be forwarded to a child component as a prop
|
|
13
|
+
content.includes('{children}') ||
|
|
14
|
+
content.includes('children={')))
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
1
18
|
/**
|
|
2
19
|
* Check if a match position is within a comment or a string
|
|
3
20
|
* @param {string} content - The full content
|
|
@@ -605,7 +605,8 @@ async function initialize(result, target, hydrate) {
|
|
|
605
605
|
to: {
|
|
606
606
|
params: current.params,
|
|
607
607
|
route: { id: current.route?.id ?? null },
|
|
608
|
-
url: new URL(location.href)
|
|
608
|
+
url: new URL(location.href),
|
|
609
|
+
scroll: scroll_positions[current_history_index] ?? scroll_state()
|
|
609
610
|
},
|
|
610
611
|
willUnload: false,
|
|
611
612
|
type: 'enter',
|
|
@@ -1463,12 +1464,13 @@ function get_page_key(url) {
|
|
|
1463
1464
|
* intent?: import('./types.js').NavigationIntent;
|
|
1464
1465
|
* delta?: number;
|
|
1465
1466
|
* event?: PopStateEvent | MouseEvent;
|
|
1467
|
+
* scroll?: { x: number, y: number };
|
|
1466
1468
|
* }} opts
|
|
1467
1469
|
*/
|
|
1468
|
-
function _before_navigate({ url, type, intent, delta, event }) {
|
|
1470
|
+
function _before_navigate({ url, type, intent, delta, event, scroll }) {
|
|
1469
1471
|
let should_block = false;
|
|
1470
1472
|
|
|
1471
|
-
const nav = create_navigation(current, intent, url, type);
|
|
1473
|
+
const nav = create_navigation(current, intent, url, type, scroll ?? null);
|
|
1472
1474
|
|
|
1473
1475
|
if (delta !== undefined) {
|
|
1474
1476
|
nav.navigation.delta = delta;
|
|
@@ -1543,6 +1545,7 @@ async function navigate({
|
|
|
1543
1545
|
type,
|
|
1544
1546
|
delta: popped?.delta,
|
|
1545
1547
|
intent,
|
|
1548
|
+
scroll: popped?.scroll,
|
|
1546
1549
|
// @ts-ignore
|
|
1547
1550
|
event
|
|
1548
1551
|
});
|
|
@@ -1808,6 +1811,11 @@ async function navigate({
|
|
|
1808
1811
|
|
|
1809
1812
|
nav.fulfil(undefined);
|
|
1810
1813
|
|
|
1814
|
+
// Update to.scroll to the actual scroll position after navigation completed
|
|
1815
|
+
if (nav.navigation.to) {
|
|
1816
|
+
nav.navigation.to.scroll = scroll_state();
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1811
1819
|
after_navigate_callbacks.forEach((fn) =>
|
|
1812
1820
|
fn(/** @type {import('@sveltejs/kit').AfterNavigate} */ (nav.navigation))
|
|
1813
1821
|
);
|
|
@@ -3013,20 +3021,12 @@ function reset_focus(url, scroll = null) {
|
|
|
3013
3021
|
const history_state = history.state;
|
|
3014
3022
|
|
|
3015
3023
|
resetting_focus = true;
|
|
3016
|
-
location.replace(`#${id}
|
|
3024
|
+
location.replace(new URL(`#${id}`, location.href));
|
|
3017
3025
|
|
|
3018
|
-
//
|
|
3019
|
-
//
|
|
3020
|
-
//
|
|
3021
|
-
|
|
3022
|
-
if (app.hash) {
|
|
3023
|
-
location.replace(url.hash);
|
|
3024
|
-
}
|
|
3025
|
-
|
|
3026
|
-
// but Firefox has a bug that sets the history state to `null` so we
|
|
3027
|
-
// need to restore it after.
|
|
3028
|
-
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1199924
|
|
3029
|
-
history.replaceState(history_state, '', url.hash);
|
|
3026
|
+
// Firefox has a bug that sets the history state to `null` so we need to
|
|
3027
|
+
// restore it after. See https://bugzilla.mozilla.org/show_bug.cgi?id=1199924
|
|
3028
|
+
// This is also needed to restore the original hash if we're using hash routing
|
|
3029
|
+
history.replaceState(history_state, '', url);
|
|
3030
3030
|
|
|
3031
3031
|
// Scroll management has already happened earlier so we need to restore
|
|
3032
3032
|
// the scroll position after setting the sequential focus navigation starting point
|
|
@@ -3102,8 +3102,9 @@ function reset_focus(url, scroll = null) {
|
|
|
3102
3102
|
* @param {import('./types.js').NavigationIntent | undefined} intent
|
|
3103
3103
|
* @param {URL | null} url
|
|
3104
3104
|
* @param {T} type
|
|
3105
|
+
* @param {{ x: number, y: number } | null} [target_scroll] The scroll position for the target (for popstate navigations)
|
|
3105
3106
|
*/
|
|
3106
|
-
function create_navigation(current, intent, url, type) {
|
|
3107
|
+
function create_navigation(current, intent, url, type, target_scroll = null) {
|
|
3107
3108
|
/** @type {(value: any) => void} */
|
|
3108
3109
|
let fulfil;
|
|
3109
3110
|
|
|
@@ -3123,12 +3124,14 @@ function create_navigation(current, intent, url, type) {
|
|
|
3123
3124
|
from: {
|
|
3124
3125
|
params: current.params,
|
|
3125
3126
|
route: { id: current.route?.id ?? null },
|
|
3126
|
-
url: current.url
|
|
3127
|
+
url: current.url,
|
|
3128
|
+
scroll: scroll_state()
|
|
3127
3129
|
},
|
|
3128
3130
|
to: url && {
|
|
3129
3131
|
params: intent?.params ?? null,
|
|
3130
3132
|
route: { id: intent?.route?.id ?? null },
|
|
3131
|
-
url
|
|
3133
|
+
url,
|
|
3134
|
+
scroll: target_scroll
|
|
3132
3135
|
},
|
|
3133
3136
|
willUnload: !intent,
|
|
3134
3137
|
type,
|
|
@@ -55,7 +55,12 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade
|
|
|
55
55
|
request.headers.delete('origin');
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
const decoded = decodeURIComponent(url.pathname);
|
|
59
|
+
|
|
60
|
+
if (
|
|
61
|
+
url.origin !== event.url.origin ||
|
|
62
|
+
(paths.base && decoded !== paths.base && !decoded.startsWith(`${paths.base}/`))
|
|
63
|
+
) {
|
|
59
64
|
// Allow cookie passthrough for "credentials: same-origin" and "credentials: include"
|
|
60
65
|
// if SvelteKit is serving my.domain.com:
|
|
61
66
|
// - domain.com WILL NOT receive cookies
|
|
@@ -77,7 +82,6 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade
|
|
|
77
82
|
// handle fetch requests for static assets. e.g. prebaked data, etc.
|
|
78
83
|
// we need to support everything the browser's fetch supports
|
|
79
84
|
const prefix = paths.assets || paths.base;
|
|
80
|
-
const decoded = decodeURIComponent(url.pathname);
|
|
81
85
|
const filename = (
|
|
82
86
|
decoded.startsWith(prefix) ? decoded.slice(prefix.length) : decoded
|
|
83
87
|
).slice(1);
|
|
@@ -53,21 +53,30 @@ class BaseProvider {
|
|
|
53
53
|
/** @type {import('types').CspDirectives} */
|
|
54
54
|
#directives;
|
|
55
55
|
|
|
56
|
-
/** @type {import('types').Csp.Source
|
|
56
|
+
/** @type {Set<import('types').Csp.Source>} */
|
|
57
57
|
#script_src;
|
|
58
58
|
|
|
59
|
-
/** @type {import('types').Csp.Source
|
|
59
|
+
/** @type {Set<import('types').Csp.Source>} */
|
|
60
60
|
#script_src_elem;
|
|
61
61
|
|
|
62
|
-
/** @type {import('types').Csp.Source
|
|
62
|
+
/** @type {Set<import('types').Csp.Source>} */
|
|
63
63
|
#style_src;
|
|
64
64
|
|
|
65
|
-
/** @type {import('types').Csp.Source
|
|
65
|
+
/** @type {Set<import('types').Csp.Source>} */
|
|
66
66
|
#style_src_attr;
|
|
67
67
|
|
|
68
|
-
/** @type {import('types').Csp.Source
|
|
68
|
+
/** @type {Set<import('types').Csp.Source>} */
|
|
69
69
|
#style_src_elem;
|
|
70
70
|
|
|
71
|
+
/** @type {boolean} */
|
|
72
|
+
script_needs_nonce;
|
|
73
|
+
|
|
74
|
+
/** @type {boolean} */
|
|
75
|
+
style_needs_nonce;
|
|
76
|
+
|
|
77
|
+
/** @type {boolean} */
|
|
78
|
+
script_needs_hash;
|
|
79
|
+
|
|
71
80
|
/** @type {string} */
|
|
72
81
|
#nonce;
|
|
73
82
|
|
|
@@ -82,11 +91,11 @@ class BaseProvider {
|
|
|
82
91
|
|
|
83
92
|
const d = this.#directives;
|
|
84
93
|
|
|
85
|
-
this.#script_src =
|
|
86
|
-
this.#script_src_elem =
|
|
87
|
-
this.#style_src =
|
|
88
|
-
this.#style_src_attr =
|
|
89
|
-
this.#style_src_elem =
|
|
94
|
+
this.#script_src = new Set();
|
|
95
|
+
this.#script_src_elem = new Set();
|
|
96
|
+
this.#style_src = new Set();
|
|
97
|
+
this.#style_src_attr = new Set();
|
|
98
|
+
this.#style_src_elem = new Set();
|
|
90
99
|
|
|
91
100
|
const effective_script_src = d['script-src'] || d['default-src'];
|
|
92
101
|
const script_src_elem = d['script-src-elem'];
|
|
@@ -162,6 +171,7 @@ class BaseProvider {
|
|
|
162
171
|
|
|
163
172
|
this.script_needs_nonce = this.#script_needs_csp && !this.#use_hashes;
|
|
164
173
|
this.style_needs_nonce = this.#style_needs_csp && !this.#use_hashes;
|
|
174
|
+
this.script_needs_hash = this.#script_needs_csp && this.#use_hashes;
|
|
165
175
|
|
|
166
176
|
this.#nonce = nonce;
|
|
167
177
|
}
|
|
@@ -174,11 +184,23 @@ class BaseProvider {
|
|
|
174
184
|
const source = this.#use_hashes ? `sha256-${sha256(content)}` : `nonce-${this.#nonce}`;
|
|
175
185
|
|
|
176
186
|
if (this.#script_src_needs_csp) {
|
|
177
|
-
this.#script_src.
|
|
187
|
+
this.#script_src.add(source);
|
|
178
188
|
}
|
|
179
189
|
|
|
180
190
|
if (this.#script_src_elem_needs_csp) {
|
|
181
|
-
this.#script_src_elem.
|
|
191
|
+
this.#script_src_elem.add(source);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** @param {`sha256-${string}`[]} hashes */
|
|
196
|
+
add_script_hashes(hashes) {
|
|
197
|
+
for (const hash of hashes) {
|
|
198
|
+
if (this.#script_src_needs_csp) {
|
|
199
|
+
this.#script_src.add(hash);
|
|
200
|
+
}
|
|
201
|
+
if (this.#script_src_elem_needs_csp) {
|
|
202
|
+
this.#script_src_elem.add(hash);
|
|
203
|
+
}
|
|
182
204
|
}
|
|
183
205
|
}
|
|
184
206
|
|
|
@@ -190,11 +212,11 @@ class BaseProvider {
|
|
|
190
212
|
const source = this.#use_hashes ? `sha256-${sha256(content)}` : `nonce-${this.#nonce}`;
|
|
191
213
|
|
|
192
214
|
if (this.#style_src_needs_csp) {
|
|
193
|
-
this.#style_src.
|
|
215
|
+
this.#style_src.add(source);
|
|
194
216
|
}
|
|
195
217
|
|
|
196
218
|
if (this.#style_src_attr_needs_csp) {
|
|
197
|
-
this.#style_src_attr.
|
|
219
|
+
this.#style_src_attr.add(source);
|
|
198
220
|
}
|
|
199
221
|
|
|
200
222
|
if (this.#style_src_elem_needs_csp) {
|
|
@@ -207,13 +229,13 @@ class BaseProvider {
|
|
|
207
229
|
if (
|
|
208
230
|
d['style-src-elem'] &&
|
|
209
231
|
!d['style-src-elem'].includes(sha256_empty_comment_hash) &&
|
|
210
|
-
!this.#style_src_elem.
|
|
232
|
+
!this.#style_src_elem.has(sha256_empty_comment_hash)
|
|
211
233
|
) {
|
|
212
|
-
this.#style_src_elem.
|
|
234
|
+
this.#style_src_elem.add(sha256_empty_comment_hash);
|
|
213
235
|
}
|
|
214
236
|
|
|
215
237
|
if (source !== sha256_empty_comment_hash) {
|
|
216
|
-
this.#style_src_elem.
|
|
238
|
+
this.#style_src_elem.add(source);
|
|
217
239
|
}
|
|
218
240
|
}
|
|
219
241
|
}
|
|
@@ -230,35 +252,35 @@ class BaseProvider {
|
|
|
230
252
|
|
|
231
253
|
const directives = { ...this.#directives };
|
|
232
254
|
|
|
233
|
-
if (this.#style_src.
|
|
255
|
+
if (this.#style_src.size > 0) {
|
|
234
256
|
directives['style-src'] = [
|
|
235
257
|
...(directives['style-src'] || directives['default-src'] || []),
|
|
236
258
|
...this.#style_src
|
|
237
259
|
];
|
|
238
260
|
}
|
|
239
261
|
|
|
240
|
-
if (this.#style_src_attr.
|
|
262
|
+
if (this.#style_src_attr.size > 0) {
|
|
241
263
|
directives['style-src-attr'] = [
|
|
242
264
|
...(directives['style-src-attr'] || []),
|
|
243
265
|
...this.#style_src_attr
|
|
244
266
|
];
|
|
245
267
|
}
|
|
246
268
|
|
|
247
|
-
if (this.#style_src_elem.
|
|
269
|
+
if (this.#style_src_elem.size > 0) {
|
|
248
270
|
directives['style-src-elem'] = [
|
|
249
271
|
...(directives['style-src-elem'] || []),
|
|
250
272
|
...this.#style_src_elem
|
|
251
273
|
];
|
|
252
274
|
}
|
|
253
275
|
|
|
254
|
-
if (this.#script_src.
|
|
276
|
+
if (this.#script_src.size > 0) {
|
|
255
277
|
directives['script-src'] = [
|
|
256
278
|
...(directives['script-src'] || directives['default-src'] || []),
|
|
257
279
|
...this.#script_src
|
|
258
280
|
];
|
|
259
281
|
}
|
|
260
282
|
|
|
261
|
-
if (this.#script_src_elem.
|
|
283
|
+
if (this.#script_src_elem.size > 0) {
|
|
262
284
|
directives['script-src-elem'] = [
|
|
263
285
|
...(directives['script-src-elem'] || []),
|
|
264
286
|
...this.#script_src_elem
|
|
@@ -351,6 +373,10 @@ export class Csp {
|
|
|
351
373
|
this.report_only_provider = new CspReportOnlyProvider(use_hashes, reportOnly, this.nonce);
|
|
352
374
|
}
|
|
353
375
|
|
|
376
|
+
get script_needs_hash() {
|
|
377
|
+
return this.csp_provider.script_needs_hash || this.report_only_provider.script_needs_hash;
|
|
378
|
+
}
|
|
379
|
+
|
|
354
380
|
get script_needs_nonce() {
|
|
355
381
|
return this.csp_provider.script_needs_nonce || this.report_only_provider.script_needs_nonce;
|
|
356
382
|
}
|
|
@@ -365,6 +391,12 @@ export class Csp {
|
|
|
365
391
|
this.report_only_provider.add_script(content);
|
|
366
392
|
}
|
|
367
393
|
|
|
394
|
+
/** @param {`sha256-${string}`[]} hashes */
|
|
395
|
+
add_script_hashes(hashes) {
|
|
396
|
+
this.csp_provider.add_script_hashes(hashes);
|
|
397
|
+
this.report_only_provider.add_script_hashes(hashes);
|
|
398
|
+
}
|
|
399
|
+
|
|
368
400
|
/** @param {string} content */
|
|
369
401
|
add_style(content) {
|
|
370
402
|
this.csp_provider.add_style(content);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { text } from '@sveltejs/kit';
|
|
2
|
-
import { Redirect } from '@sveltejs/kit/internal';
|
|
2
|
+
import { HttpError, Redirect } from '@sveltejs/kit/internal';
|
|
3
3
|
import { compact } from '../../../utils/array.js';
|
|
4
4
|
import { get_status, normalize_error } from '../../../utils/error.js';
|
|
5
5
|
import { add_data_suffix } from '../../pathname.js';
|
|
@@ -357,6 +357,11 @@ export async function render_page(
|
|
|
357
357
|
ssr === false ? server_data_serializer(event, event_state, options) : data_serializer
|
|
358
358
|
});
|
|
359
359
|
} catch (e) {
|
|
360
|
+
// a remote function could have thrown a redirect during render
|
|
361
|
+
if (e instanceof Redirect) {
|
|
362
|
+
return redirect_response(e.status, e.location);
|
|
363
|
+
}
|
|
364
|
+
|
|
360
365
|
// if we end up here, it means the data loaded successfully
|
|
361
366
|
// but the page failed to render, or that a prerendering error occurred
|
|
362
367
|
return await respond_with_error({
|
|
@@ -365,7 +370,7 @@ export async function render_page(
|
|
|
365
370
|
options,
|
|
366
371
|
manifest,
|
|
367
372
|
state,
|
|
368
|
-
status: 500,
|
|
373
|
+
status: e instanceof HttpError ? e.status : 500,
|
|
369
374
|
error: e,
|
|
370
375
|
resolve_opts
|
|
371
376
|
});
|
|
@@ -80,17 +80,11 @@ export async function render_response({
|
|
|
80
80
|
*/
|
|
81
81
|
const link_headers = new Set();
|
|
82
82
|
|
|
83
|
-
/**
|
|
84
|
-
* `<link>` tags that are added to prerendered responses
|
|
85
|
-
* (note that stylesheets are always added, prerendered or not)
|
|
86
|
-
* @type {Set<string>}
|
|
87
|
-
*/
|
|
88
|
-
const link_tags = new Set();
|
|
89
|
-
|
|
90
83
|
/** @type {Map<string, string>} */
|
|
91
84
|
// TODO if we add a client entry point one day, we will need to include inline_styles with the entry, otherwise stylesheets will be linked even if they are below inlineStyleThreshold
|
|
92
85
|
const inline_styles = new Map();
|
|
93
86
|
|
|
87
|
+
/** @type {ReturnType<typeof options.root.render>} */
|
|
94
88
|
let rendered;
|
|
95
89
|
|
|
96
90
|
const form_value =
|
|
@@ -110,6 +104,10 @@ export async function render_response({
|
|
|
110
104
|
*/
|
|
111
105
|
let base_expression = s(paths.base);
|
|
112
106
|
|
|
107
|
+
const csp = new Csp(options.csp, {
|
|
108
|
+
prerender: !!state.prerendering
|
|
109
|
+
});
|
|
110
|
+
|
|
113
111
|
// if appropriate, use relative paths for greater portability
|
|
114
112
|
if (paths.relative) {
|
|
115
113
|
if (!state.prerendering?.fallback) {
|
|
@@ -177,7 +175,8 @@ export async function render_response({
|
|
|
177
175
|
page: props.page
|
|
178
176
|
}
|
|
179
177
|
]
|
|
180
|
-
])
|
|
178
|
+
]),
|
|
179
|
+
csp: csp.script_needs_nonce ? { nonce: csp.nonce } : { hash: csp.script_needs_hash }
|
|
181
180
|
};
|
|
182
181
|
|
|
183
182
|
const fetch = globalThis.fetch;
|
|
@@ -227,9 +226,15 @@ export async function render_response({
|
|
|
227
226
|
paths.reset();
|
|
228
227
|
}
|
|
229
228
|
|
|
230
|
-
const { head, html, css } =
|
|
229
|
+
const { head, html, css, hashes } = /** @type {ReturnType<typeof options.root.render>} */ (
|
|
230
|
+
options.async ? await rendered : rendered
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
if (hashes) {
|
|
234
|
+
csp.add_script_hashes(hashes.script);
|
|
235
|
+
}
|
|
231
236
|
|
|
232
|
-
return { head, html, css };
|
|
237
|
+
return { head, html, css, hashes };
|
|
233
238
|
});
|
|
234
239
|
} finally {
|
|
235
240
|
if (DEV) {
|
|
@@ -256,16 +261,12 @@ export async function render_response({
|
|
|
256
261
|
}
|
|
257
262
|
}
|
|
258
263
|
} else {
|
|
259
|
-
rendered = { head: '', html: '', css: { code: '', map: null } };
|
|
264
|
+
rendered = { head: '', html: '', css: { code: '', map: null }, hashes: { script: [] } };
|
|
260
265
|
}
|
|
261
266
|
|
|
262
|
-
|
|
267
|
+
const head = new Head(rendered.head, !!state.prerendering);
|
|
263
268
|
let body = rendered.html;
|
|
264
269
|
|
|
265
|
-
const csp = new Csp(options.csp, {
|
|
266
|
-
prerender: !!state.prerendering
|
|
267
|
-
});
|
|
268
|
-
|
|
269
270
|
/** @param {string} path */
|
|
270
271
|
const prefixed = (path) => {
|
|
271
272
|
if (path.startsWith('/')) {
|
|
@@ -283,12 +284,10 @@ export async function render_response({
|
|
|
283
284
|
: Array.from(inline_styles.values()).join('\n');
|
|
284
285
|
|
|
285
286
|
if (style) {
|
|
286
|
-
const attributes = DEV ? ['
|
|
287
|
-
if (csp.style_needs_nonce) attributes.push(`
|
|
288
|
-
|
|
287
|
+
const attributes = DEV ? ['data-sveltekit'] : [];
|
|
288
|
+
if (csp.style_needs_nonce) attributes.push(`nonce="${csp.nonce}"`);
|
|
289
289
|
csp.add_style(style);
|
|
290
|
-
|
|
291
|
-
head += `\n\t<style${attributes.join('')}>${style}</style>`;
|
|
290
|
+
head.add_style(style, attributes);
|
|
292
291
|
}
|
|
293
292
|
|
|
294
293
|
for (const dep of stylesheets) {
|
|
@@ -306,7 +305,7 @@ export async function render_response({
|
|
|
306
305
|
}
|
|
307
306
|
}
|
|
308
307
|
|
|
309
|
-
head
|
|
308
|
+
head.add_stylesheet(path, attributes);
|
|
310
309
|
}
|
|
311
310
|
|
|
312
311
|
for (const dep of fonts) {
|
|
@@ -315,7 +314,7 @@ export async function render_response({
|
|
|
315
314
|
if (resolve_opts.preload({ type: 'font', path })) {
|
|
316
315
|
const ext = dep.slice(dep.lastIndexOf('.') + 1);
|
|
317
316
|
|
|
318
|
-
|
|
317
|
+
head.add_link_tag(path, ['rel="preload"', 'as="font"', `type="font/${ext}"`, 'crossorigin']);
|
|
319
318
|
|
|
320
319
|
link_headers.add(
|
|
321
320
|
`<${encodeURI(path)}>; rel="preload"; as="font"; type="font/${ext}"; crossorigin; nopush`
|
|
@@ -351,19 +350,13 @@ export async function render_response({
|
|
|
351
350
|
link_headers.add(`<${encodeURI(path)}>; rel="modulepreload"; nopush`);
|
|
352
351
|
|
|
353
352
|
if (options.preload_strategy !== 'modulepreload') {
|
|
354
|
-
head
|
|
353
|
+
head.add_script_preload(path);
|
|
355
354
|
} else {
|
|
356
|
-
|
|
355
|
+
head.add_link_tag(path, ['rel="modulepreload"']);
|
|
357
356
|
}
|
|
358
357
|
}
|
|
359
358
|
}
|
|
360
359
|
|
|
361
|
-
if (state.prerendering && link_tags.size > 0) {
|
|
362
|
-
head += Array.from(link_tags)
|
|
363
|
-
.map((tag) => `\n\t\t${tag}`)
|
|
364
|
-
.join('');
|
|
365
|
-
}
|
|
366
|
-
|
|
367
360
|
// prerender a `/path/to/page/__route.js` module
|
|
368
361
|
if (manifest._.client.routes && state.prerendering && !state.prerendering.fallback) {
|
|
369
362
|
const pathname = add_resolution_suffix(event.url.pathname);
|
|
@@ -581,19 +574,15 @@ export async function render_response({
|
|
|
581
574
|
|
|
582
575
|
if (state.prerendering) {
|
|
583
576
|
// TODO read headers set with setHeaders and convert into http-equiv where possible
|
|
584
|
-
const http_equiv = [];
|
|
585
|
-
|
|
586
577
|
const csp_headers = csp.csp_provider.get_meta();
|
|
587
578
|
if (csp_headers) {
|
|
588
|
-
|
|
579
|
+
head.add_http_equiv(csp_headers);
|
|
589
580
|
}
|
|
590
581
|
|
|
591
582
|
if (state.prerendering.cache) {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
if (http_equiv.length > 0) {
|
|
596
|
-
head = http_equiv.join('\n') + head;
|
|
583
|
+
head.add_http_equiv(
|
|
584
|
+
`<meta http-equiv="cache-control" content="${state.prerendering.cache}">`
|
|
585
|
+
);
|
|
597
586
|
}
|
|
598
587
|
} else {
|
|
599
588
|
const csp_header = csp.csp_provider.get_header();
|
|
@@ -610,11 +599,8 @@ export async function render_response({
|
|
|
610
599
|
}
|
|
611
600
|
}
|
|
612
601
|
|
|
613
|
-
// add the content after the script/css links so the link elements are parsed first
|
|
614
|
-
head += rendered.head;
|
|
615
|
-
|
|
616
602
|
const html = options.templates.app({
|
|
617
|
-
head,
|
|
603
|
+
head: head.build(),
|
|
618
604
|
body,
|
|
619
605
|
assets,
|
|
620
606
|
nonce: /** @type {string} */ (csp.nonce),
|
|
@@ -672,3 +658,78 @@ export async function render_response({
|
|
|
672
658
|
}
|
|
673
659
|
);
|
|
674
660
|
}
|
|
661
|
+
|
|
662
|
+
class Head {
|
|
663
|
+
#rendered;
|
|
664
|
+
#prerendering;
|
|
665
|
+
/** @type {string[]} */
|
|
666
|
+
#http_equiv = [];
|
|
667
|
+
/** @type {string[]} */
|
|
668
|
+
#link_tags = [];
|
|
669
|
+
/** @type {string[]} */
|
|
670
|
+
#script_preloads = [];
|
|
671
|
+
/** @type {string[]} */
|
|
672
|
+
#style_tags = [];
|
|
673
|
+
/** @type {string[]} */
|
|
674
|
+
#stylesheet_links = [];
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* @param {string} rendered
|
|
678
|
+
* @param {boolean} prerendering
|
|
679
|
+
*/
|
|
680
|
+
constructor(rendered, prerendering) {
|
|
681
|
+
this.#rendered = rendered;
|
|
682
|
+
this.#prerendering = prerendering;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
build() {
|
|
686
|
+
return [
|
|
687
|
+
...this.#http_equiv,
|
|
688
|
+
...this.#link_tags,
|
|
689
|
+
...this.#script_preloads,
|
|
690
|
+
this.#rendered,
|
|
691
|
+
...this.#style_tags,
|
|
692
|
+
...this.#stylesheet_links
|
|
693
|
+
].join('\n\t\t');
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* @param {string} style
|
|
698
|
+
* @param {string[]} attributes
|
|
699
|
+
*/
|
|
700
|
+
add_style(style, attributes) {
|
|
701
|
+
this.#style_tags.push(
|
|
702
|
+
`<style${attributes.length ? ' ' + attributes.join(' ') : ''}>${style}</style>`
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* @param {string} href
|
|
708
|
+
* @param {string[]} attributes
|
|
709
|
+
*/
|
|
710
|
+
add_stylesheet(href, attributes) {
|
|
711
|
+
this.#stylesheet_links.push(`<link href="${href}" ${attributes.join(' ')}>`);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
/** @param {string} href */
|
|
715
|
+
add_script_preload(href) {
|
|
716
|
+
this.#script_preloads.push(
|
|
717
|
+
`<link rel="preload" as="script" crossorigin="anonymous" href="${href}">`
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* @param {string} href
|
|
723
|
+
* @param {string[]} attributes
|
|
724
|
+
*/
|
|
725
|
+
add_link_tag(href, attributes) {
|
|
726
|
+
if (!this.#prerendering) return;
|
|
727
|
+
this.#link_tags.push(`<link href="${href}" ${attributes.join(' ')}>`);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/** @param {string} tag */
|
|
731
|
+
add_http_equiv(tag) {
|
|
732
|
+
if (!this.#prerendering) return;
|
|
733
|
+
this.#http_equiv.push(tag);
|
|
734
|
+
}
|
|
735
|
+
}
|
package/src/types/internal.d.ts
CHANGED
|
@@ -176,7 +176,7 @@ export class InternalServer extends Server {
|
|
|
176
176
|
request: Request,
|
|
177
177
|
options: RequestOptions & {
|
|
178
178
|
prerendering?: PrerenderOptions;
|
|
179
|
-
read: (file: string) =>
|
|
179
|
+
read: (file: string) => NonSharedBuffer;
|
|
180
180
|
/** A hook called before `handle` during dev, so that `AsyncLocalStorage` can be populated. */
|
|
181
181
|
before_handle?: (event: RequestEvent, config: any, prerender: PrerenderOption) => void;
|
|
182
182
|
emulator?: Emulator;
|
|
@@ -381,7 +381,7 @@ export interface SSRComponent {
|
|
|
381
381
|
default: {
|
|
382
382
|
render(
|
|
383
383
|
props: Record<string, any>,
|
|
384
|
-
opts: { context: Map<any, any
|
|
384
|
+
opts: { context: Map<any, any>; csp?: { nonce?: string; hash?: boolean } }
|
|
385
385
|
): {
|
|
386
386
|
html: string;
|
|
387
387
|
head: string;
|
|
@@ -389,6 +389,10 @@ export interface SSRComponent {
|
|
|
389
389
|
code: string;
|
|
390
390
|
map: any; // TODO
|
|
391
391
|
};
|
|
392
|
+
/** Until we require all Svelte versions that support hashes, this might not be defined */
|
|
393
|
+
hashes?: {
|
|
394
|
+
script: Array<`sha256-${string}`>;
|
|
395
|
+
};
|
|
392
396
|
};
|
|
393
397
|
};
|
|
394
398
|
}
|
|
@@ -525,9 +529,9 @@ export interface SSRState {
|
|
|
525
529
|
* prerender option is inherited by the endpoint, unless overridden.
|
|
526
530
|
*/
|
|
527
531
|
prerender_default?: PrerenderOption;
|
|
528
|
-
read?: (file: string) =>
|
|
532
|
+
read?: (file: string) => NonSharedBuffer;
|
|
529
533
|
/**
|
|
530
|
-
* Used to
|
|
534
|
+
* Used to set up `__SVELTEKIT_TRACK__` which checks if a used feature is supported.
|
|
531
535
|
* E.g. if `read` from `$app/server` is used, it checks whether the route's config is compatible.
|
|
532
536
|
*/
|
|
533
537
|
before_handle?: (event: RequestEvent, config: any, prerender: PrerenderOption) => void;
|
package/src/version.js
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1175,6 +1175,19 @@ declare module '@sveltejs/kit' {
|
|
|
1175
1175
|
* The URL that is navigated to
|
|
1176
1176
|
*/
|
|
1177
1177
|
url: URL;
|
|
1178
|
+
/**
|
|
1179
|
+
* The scroll position associated with this navigation.
|
|
1180
|
+
*
|
|
1181
|
+
* For the `from` target, this is the scroll position at the moment of navigation.
|
|
1182
|
+
*
|
|
1183
|
+
* For the `to` target, this represents the scroll position that will be or was restored:
|
|
1184
|
+
* - In `beforeNavigate` and `onNavigate`, this is only available for `popstate` navigations (back/forward button)
|
|
1185
|
+
* and will be `null` for other navigation types, since the final scroll position isn't known
|
|
1186
|
+
* ahead of time.
|
|
1187
|
+
* - In `afterNavigate`, this is always the scroll position that was applied after the navigation
|
|
1188
|
+
* completed.
|
|
1189
|
+
*/
|
|
1190
|
+
scroll: { x: number; y: number } | null;
|
|
1178
1191
|
}
|
|
1179
1192
|
|
|
1180
1193
|
/**
|
|
@@ -1224,7 +1237,7 @@ declare module '@sveltejs/kit' {
|
|
|
1224
1237
|
delta?: undefined;
|
|
1225
1238
|
|
|
1226
1239
|
/**
|
|
1227
|
-
* Dispatched `Event` object when navigation
|
|
1240
|
+
* Dispatched `Event` object when navigation occurred by `popstate` or `link`.
|
|
1228
1241
|
*/
|
|
1229
1242
|
event?: undefined;
|
|
1230
1243
|
}
|
|
@@ -2510,7 +2523,7 @@ declare module '@sveltejs/kit' {
|
|
|
2510
2523
|
default: {
|
|
2511
2524
|
render(
|
|
2512
2525
|
props: Record<string, any>,
|
|
2513
|
-
opts: { context: Map<any, any
|
|
2526
|
+
opts: { context: Map<any, any>; csp?: { nonce?: string; hash?: boolean } }
|
|
2514
2527
|
): {
|
|
2515
2528
|
html: string;
|
|
2516
2529
|
head: string;
|
|
@@ -2518,6 +2531,10 @@ declare module '@sveltejs/kit' {
|
|
|
2518
2531
|
code: string;
|
|
2519
2532
|
map: any; // TODO
|
|
2520
2533
|
};
|
|
2534
|
+
/** Until we require all Svelte versions that support hashes, this might not be defined */
|
|
2535
|
+
hashes?: {
|
|
2536
|
+
script: Array<`sha256-${string}`>;
|
|
2537
|
+
};
|
|
2521
2538
|
};
|
|
2522
2539
|
};
|
|
2523
2540
|
}
|
package/types/index.d.ts.map
CHANGED
|
@@ -217,6 +217,6 @@
|
|
|
217
217
|
null,
|
|
218
218
|
null
|
|
219
219
|
],
|
|
220
|
-
"mappings": ";;;;;;;;MAgCKA,IAAIA;;;;;kBAKQC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAiCZC,cAAcA;;;;;;aAMdC,cAAcA;;;;;;;;MAQrBC,aAAaA;;;;;OAKJC,YAAYA;;kBAETC,aAAaA;;;;;;MAMzBC,qBAAqBA;;;;;;;;;;;kBAWTC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA8IPC,MAAMA;;;;;;;;;;;kBAWNC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA4DPC,QAAQA;;;;;;;;kBAQRC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAykBdC,MAAMA;;;;;;;;;;;aAWNC,iBAAiBA;;;;;;;;;;;;aAYjBC,qBAAqBA;;;;;;;;;aASrBC,iBAAiBA;;;;;;;;;;aAUjBC,WAAWA;;;;;;;;;;aAUXC,UAAUA;;;;;;aAMVC,UAAUA;;;;;;aAMVC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;aA0BPC,SAASA;;;;;kBAKJC,WAAWA;;;;;;;;;;;;aAYhBC,IAAIA;;;;;;;;;;;;kBAYCC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAyHTC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;kBA0BfC,gBAAgBA
|
|
220
|
+
"mappings": "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",
|
|
221
221
|
"ignoreList": []
|
|
222
222
|
}
|