@sveltejs/kit 1.15.6 → 1.15.8
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 +4 -4
- package/src/core/adapt/builder.js +1 -1
- package/src/core/config/options.js +26 -10
- package/src/core/postbuild/prerender.js +17 -2
- package/src/exports/vite/dev/index.js +5 -12
- package/src/exports/vite/index.js +10 -10
- package/src/runtime/client/client.js +160 -195
- package/src/runtime/client/fetcher.js +5 -7
- package/src/runtime/server/page/render.js +9 -8
- package/types/index.d.ts +2 -5
- package/types/internal.d.ts +5 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.8",
|
|
4
4
|
"description": "The fastest way to build Svelte apps",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"homepage": "https://kit.svelte.dev",
|
|
12
12
|
"type": "module",
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@sveltejs/vite-plugin-svelte": "^2.
|
|
14
|
+
"@sveltejs/vite-plugin-svelte": "^2.1.0",
|
|
15
15
|
"@types/cookie": "^0.5.1",
|
|
16
16
|
"cookie": "^0.5.0",
|
|
17
17
|
"devalue": "^4.3.0",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"set-cookie-parser": "^2.5.1",
|
|
24
24
|
"sirv": "^2.0.2",
|
|
25
25
|
"tiny-glob": "^0.2.9",
|
|
26
|
-
"undici": "5.
|
|
26
|
+
"undici": "~5.22.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@playwright/test": "^1.29.2",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"svelte-preprocess": "^5.0.0",
|
|
40
40
|
"typescript": "^4.9.4",
|
|
41
41
|
"uvu": "^0.5.6",
|
|
42
|
-
"vite": "^4.
|
|
42
|
+
"vite": "^4.3.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"svelte": "^3.54.0",
|
|
@@ -162,7 +162,7 @@ export function create_builder({
|
|
|
162
162
|
relative_path: relativePath,
|
|
163
163
|
routes: subset
|
|
164
164
|
? subset.map((route) => /** @type {import('types').RouteData} */ (lookup.get(route)))
|
|
165
|
-
: route_data
|
|
165
|
+
: route_data.filter((route) => prerender_map.get(route.id) !== true)
|
|
166
166
|
});
|
|
167
167
|
},
|
|
168
168
|
|
|
@@ -201,17 +201,33 @@ const options = object(
|
|
|
201
201
|
return input;
|
|
202
202
|
}),
|
|
203
203
|
|
|
204
|
-
handleHttpError: validate(
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
204
|
+
handleHttpError: validate(
|
|
205
|
+
(/** @type {any} */ { message }) => {
|
|
206
|
+
throw new Error(
|
|
207
|
+
message +
|
|
208
|
+
`\nTo suppress or handle this error, implement \`handleHttpError\` in https://kit.svelte.dev/docs/configuration#prerender`
|
|
209
|
+
);
|
|
210
|
+
},
|
|
211
|
+
(input, keypath) => {
|
|
212
|
+
if (typeof input === 'function') return input;
|
|
213
|
+
if (['fail', 'warn', 'ignore'].includes(input)) return input;
|
|
214
|
+
throw new Error(`${keypath} should be "fail", "warn", "ignore" or a custom function`);
|
|
215
|
+
}
|
|
216
|
+
),
|
|
209
217
|
|
|
210
|
-
handleMissingId: validate(
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
218
|
+
handleMissingId: validate(
|
|
219
|
+
(/** @type {any} */ { message }) => {
|
|
220
|
+
throw new Error(
|
|
221
|
+
message +
|
|
222
|
+
`\nTo suppress or handle this error, implement \`handleMissingId\` in https://kit.svelte.dev/docs/configuration#prerender`
|
|
223
|
+
);
|
|
224
|
+
},
|
|
225
|
+
(input, keypath) => {
|
|
226
|
+
if (typeof input === 'function') return input;
|
|
227
|
+
if (['fail', 'warn', 'ignore'].includes(input)) return input;
|
|
228
|
+
throw new Error(`${keypath} should be "fail", "warn", "ignore" or a custom function`);
|
|
229
|
+
}
|
|
230
|
+
),
|
|
215
231
|
|
|
216
232
|
origin: validate('http://sveltekit-prerender', (input, keypath) => {
|
|
217
233
|
assert_string(input, keypath);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
1
|
+
import { existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
4
|
import { installPolyfills } from '../../exports/node/polyfills.js';
|
|
@@ -338,7 +338,22 @@ async function prerender({ out, manifest_path, metadata, verbose, env }) {
|
|
|
338
338
|
}
|
|
339
339
|
|
|
340
340
|
if (response.status === 200) {
|
|
341
|
-
|
|
341
|
+
if (existsSync(dest) && statSync(dest).isDirectory()) {
|
|
342
|
+
throw new Error(
|
|
343
|
+
`Cannot save ${decoded} as it is already a directory. See https://kit.svelte.dev/docs/page-options#prerender-route-conflicts for more information`
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const dir = dirname(dest);
|
|
348
|
+
|
|
349
|
+
if (existsSync(dir) && !statSync(dir).isDirectory()) {
|
|
350
|
+
const parent = decoded.split('/').slice(0, -1).join('/');
|
|
351
|
+
throw new Error(
|
|
352
|
+
`Cannot save ${decoded} as ${parent} is already a file. See https://kit.svelte.dev/docs/page-options#prerender-route-conflicts for more information`
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
mkdirp(dir);
|
|
342
357
|
|
|
343
358
|
log.info(`${response.status} ${decoded}`);
|
|
344
359
|
writeFileSync(dest, body);
|
|
@@ -115,18 +115,11 @@ export async function dev(vite, vite_config, svelte_config) {
|
|
|
115
115
|
mimeTypes: get_mime_lookup(manifest_data),
|
|
116
116
|
_: {
|
|
117
117
|
client: {
|
|
118
|
-
start: {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
},
|
|
124
|
-
app: {
|
|
125
|
-
file: `${svelte_config.kit.outDir}/generated/client/app.js`,
|
|
126
|
-
imports: [],
|
|
127
|
-
stylesheets: [],
|
|
128
|
-
fonts: []
|
|
129
|
-
}
|
|
118
|
+
start: `${runtime_base}/client/start.js`,
|
|
119
|
+
app: `${svelte_config.kit.outDir}/generated/client/app.js`,
|
|
120
|
+
imports: [],
|
|
121
|
+
stylesheets: [],
|
|
122
|
+
fonts: []
|
|
130
123
|
},
|
|
131
124
|
nodes: manifest_data.nodes.map((node, index) => {
|
|
132
125
|
return async () => {
|
|
@@ -726,17 +726,17 @@ function kit({ svelte_config }) {
|
|
|
726
726
|
/** @type {import('vite').Manifest} */
|
|
727
727
|
const client_manifest = JSON.parse(read(`${out}/client/${vite_config.build.manifest}`));
|
|
728
728
|
|
|
729
|
+
const deps_of = /** @param {string} f */ (f) =>
|
|
730
|
+
find_deps(client_manifest, posixify(path.relative('.', f)), false);
|
|
731
|
+
const start = deps_of(`${runtime_directory}/client/start.js`);
|
|
732
|
+
const app = deps_of(`${kit.outDir}/generated/client-optimized/app.js`);
|
|
733
|
+
|
|
729
734
|
build_data.client = {
|
|
730
|
-
start:
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
app: find_deps(
|
|
736
|
-
client_manifest,
|
|
737
|
-
posixify(path.relative('.', `${kit.outDir}/generated/client-optimized/app.js`)),
|
|
738
|
-
false
|
|
739
|
-
)
|
|
735
|
+
start: start.file,
|
|
736
|
+
app: app.file,
|
|
737
|
+
imports: [...start.imports, ...app.imports],
|
|
738
|
+
stylesheets: [...start.stylesheets, ...app.stylesheets],
|
|
739
|
+
fonts: [...start.fonts, ...app.fonts]
|
|
740
740
|
};
|
|
741
741
|
|
|
742
742
|
const css = output.filter(
|
|
@@ -162,7 +162,18 @@ export function create_client(app, target) {
|
|
|
162
162
|
// was then triggered and is still running while the invalidation kicks in,
|
|
163
163
|
// at which point the invalidation should take over and "win".
|
|
164
164
|
load_cache = null;
|
|
165
|
-
|
|
165
|
+
|
|
166
|
+
const nav_token = (token = {});
|
|
167
|
+
const navigation_result = intent && (await load_route(intent));
|
|
168
|
+
if (nav_token !== token) return;
|
|
169
|
+
|
|
170
|
+
if (navigation_result) {
|
|
171
|
+
if (navigation_result.type === 'redirect') {
|
|
172
|
+
return goto(new URL(navigation_result.location, url).href, {}, [url.pathname], nav_token);
|
|
173
|
+
} else {
|
|
174
|
+
root.$set(navigation_result.props);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
166
177
|
}
|
|
167
178
|
|
|
168
179
|
/** @param {number} index */
|
|
@@ -256,183 +267,6 @@ export function create_client(app, target) {
|
|
|
256
267
|
await Promise.all(promises);
|
|
257
268
|
}
|
|
258
269
|
|
|
259
|
-
/**
|
|
260
|
-
* Returns `true` if update completes, `false` if it is aborted
|
|
261
|
-
* @param {import('./types').NavigationIntent | undefined} intent
|
|
262
|
-
* @param {URL} url
|
|
263
|
-
* @param {string[]} redirect_chain
|
|
264
|
-
* @param {number} [previous_history_index]
|
|
265
|
-
* @param {{hash?: string, scroll: { x: number, y: number } | null, keepfocus: boolean, details: { replaceState: boolean, state: any } | null}} [opts]
|
|
266
|
-
* @param {{}} [nav_token] To distinguish between different navigation events and determine the latest. Needed for example for redirects to keep the original token
|
|
267
|
-
* @param {() => void} [callback]
|
|
268
|
-
*/
|
|
269
|
-
async function update(
|
|
270
|
-
intent,
|
|
271
|
-
url,
|
|
272
|
-
redirect_chain,
|
|
273
|
-
previous_history_index,
|
|
274
|
-
opts,
|
|
275
|
-
nav_token = {},
|
|
276
|
-
callback
|
|
277
|
-
) {
|
|
278
|
-
token = nav_token;
|
|
279
|
-
let navigation_result = intent && (await load_route(intent));
|
|
280
|
-
|
|
281
|
-
if (!navigation_result) {
|
|
282
|
-
if (is_external_url(url, base)) {
|
|
283
|
-
return await native_navigation(url);
|
|
284
|
-
}
|
|
285
|
-
navigation_result = await server_fallback(
|
|
286
|
-
url,
|
|
287
|
-
{ id: null },
|
|
288
|
-
await handle_error(new Error(`Not found: ${url.pathname}`), {
|
|
289
|
-
url,
|
|
290
|
-
params: {},
|
|
291
|
-
route: { id: null }
|
|
292
|
-
}),
|
|
293
|
-
404
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// if this is an internal navigation intent, use the normalized
|
|
298
|
-
// URL for the rest of the function
|
|
299
|
-
url = intent?.url || url;
|
|
300
|
-
|
|
301
|
-
// abort if user navigated during update
|
|
302
|
-
if (token !== nav_token) return false;
|
|
303
|
-
|
|
304
|
-
if (navigation_result.type === 'redirect') {
|
|
305
|
-
if (redirect_chain.length > 10 || redirect_chain.includes(url.pathname)) {
|
|
306
|
-
navigation_result = await load_root_error_page({
|
|
307
|
-
status: 500,
|
|
308
|
-
error: await handle_error(new Error('Redirect loop'), {
|
|
309
|
-
url,
|
|
310
|
-
params: {},
|
|
311
|
-
route: { id: null }
|
|
312
|
-
}),
|
|
313
|
-
url,
|
|
314
|
-
route: { id: null }
|
|
315
|
-
});
|
|
316
|
-
} else {
|
|
317
|
-
goto(
|
|
318
|
-
new URL(navigation_result.location, url).href,
|
|
319
|
-
{},
|
|
320
|
-
[...redirect_chain, url.pathname],
|
|
321
|
-
nav_token
|
|
322
|
-
);
|
|
323
|
-
return false;
|
|
324
|
-
}
|
|
325
|
-
} else if (/** @type {number} */ (navigation_result.props.page?.status) >= 400) {
|
|
326
|
-
const updated = await stores.updated.check();
|
|
327
|
-
if (updated) {
|
|
328
|
-
await native_navigation(url);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// reset invalidation only after a finished navigation. If there are redirects or
|
|
333
|
-
// additional invalidations, they should get the same invalidation treatment
|
|
334
|
-
invalidated.length = 0;
|
|
335
|
-
force_invalidation = false;
|
|
336
|
-
|
|
337
|
-
updating = true;
|
|
338
|
-
|
|
339
|
-
// `previous_history_index` will be undefined for invalidation
|
|
340
|
-
if (previous_history_index) {
|
|
341
|
-
update_scroll_positions(previous_history_index);
|
|
342
|
-
capture_snapshot(previous_history_index);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// ensure the url pathname matches the page's trailing slash option
|
|
346
|
-
if (
|
|
347
|
-
navigation_result.props.page?.url &&
|
|
348
|
-
navigation_result.props.page.url.pathname !== url.pathname
|
|
349
|
-
) {
|
|
350
|
-
url.pathname = navigation_result.props.page?.url.pathname;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
if (opts && opts.details) {
|
|
354
|
-
const { details } = opts;
|
|
355
|
-
const change = details.replaceState ? 0 : 1;
|
|
356
|
-
details.state[INDEX_KEY] = current_history_index += change;
|
|
357
|
-
history[details.replaceState ? 'replaceState' : 'pushState'](details.state, '', url);
|
|
358
|
-
|
|
359
|
-
if (!details.replaceState) {
|
|
360
|
-
// if we navigated back, then pushed a new state, we can
|
|
361
|
-
// release memory by pruning the scroll/snapshot lookup
|
|
362
|
-
let i = current_history_index + 1;
|
|
363
|
-
while (snapshots[i] || scroll_positions[i]) {
|
|
364
|
-
delete snapshots[i];
|
|
365
|
-
delete scroll_positions[i];
|
|
366
|
-
i += 1;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// reset preload synchronously after the history state has been set to avoid race conditions
|
|
372
|
-
load_cache = null;
|
|
373
|
-
|
|
374
|
-
if (started) {
|
|
375
|
-
current = navigation_result.state;
|
|
376
|
-
|
|
377
|
-
// reset url before updating page store
|
|
378
|
-
if (navigation_result.props.page) {
|
|
379
|
-
navigation_result.props.page.url = url;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
root.$set(navigation_result.props);
|
|
383
|
-
} else {
|
|
384
|
-
initialize(navigation_result);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// opts must be passed if we're navigating
|
|
388
|
-
if (opts) {
|
|
389
|
-
const { scroll, keepfocus } = opts;
|
|
390
|
-
const { activeElement } = document;
|
|
391
|
-
|
|
392
|
-
// need to render the DOM before we can scroll to the rendered elements and do focus management
|
|
393
|
-
await tick();
|
|
394
|
-
|
|
395
|
-
// we reset scroll before dealing with focus, to avoid a flash of unscrolled content
|
|
396
|
-
if (autoscroll) {
|
|
397
|
-
const deep_linked =
|
|
398
|
-
url.hash && document.getElementById(decodeURIComponent(url.hash.slice(1)));
|
|
399
|
-
if (scroll) {
|
|
400
|
-
scrollTo(scroll.x, scroll.y);
|
|
401
|
-
} else if (deep_linked) {
|
|
402
|
-
// Here we use `scrollIntoView` on the element instead of `scrollTo`
|
|
403
|
-
// because it natively supports the `scroll-margin` and `scroll-behavior`
|
|
404
|
-
// CSS properties.
|
|
405
|
-
deep_linked.scrollIntoView();
|
|
406
|
-
} else {
|
|
407
|
-
scrollTo(0, 0);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
const changed_focus =
|
|
412
|
-
// reset focus only if any manual focus management didn't override it
|
|
413
|
-
document.activeElement !== activeElement &&
|
|
414
|
-
// also refocus when activeElement is body already because the
|
|
415
|
-
// focus event might not have been fired on it yet
|
|
416
|
-
document.activeElement !== document.body;
|
|
417
|
-
|
|
418
|
-
if (!keepfocus && !changed_focus) {
|
|
419
|
-
await reset_focus();
|
|
420
|
-
}
|
|
421
|
-
} else {
|
|
422
|
-
await tick();
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
autoscroll = true;
|
|
426
|
-
|
|
427
|
-
if (navigation_result.props.page) {
|
|
428
|
-
page = navigation_result.props.page;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
if (callback) callback();
|
|
432
|
-
|
|
433
|
-
updating = false;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
270
|
/** @param {import('./types').NavigationFinished} result */
|
|
437
271
|
function initialize(result) {
|
|
438
272
|
if (DEV && document.querySelector('vite-error-overlay')) return;
|
|
@@ -1131,7 +965,7 @@ export function create_client(app, target) {
|
|
|
1131
965
|
details,
|
|
1132
966
|
type,
|
|
1133
967
|
delta,
|
|
1134
|
-
nav_token,
|
|
968
|
+
nav_token = {},
|
|
1135
969
|
accepted,
|
|
1136
970
|
blocked
|
|
1137
971
|
}) {
|
|
@@ -1154,25 +988,156 @@ export function create_client(app, target) {
|
|
|
1154
988
|
stores.navigating.set(navigation);
|
|
1155
989
|
}
|
|
1156
990
|
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
991
|
+
token = nav_token;
|
|
992
|
+
let navigation_result = intent && (await load_route(intent));
|
|
993
|
+
|
|
994
|
+
if (!navigation_result) {
|
|
995
|
+
if (is_external_url(url, base)) {
|
|
996
|
+
return await native_navigation(url);
|
|
997
|
+
}
|
|
998
|
+
navigation_result = await server_fallback(
|
|
999
|
+
url,
|
|
1000
|
+
{ id: null },
|
|
1001
|
+
await handle_error(new Error(`Not found: ${url.pathname}`), {
|
|
1002
|
+
url,
|
|
1003
|
+
params: {},
|
|
1004
|
+
route: { id: null }
|
|
1005
|
+
}),
|
|
1006
|
+
404
|
|
1007
|
+
);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
// if this is an internal navigation intent, use the normalized
|
|
1011
|
+
// URL for the rest of the function
|
|
1012
|
+
url = intent?.url || url;
|
|
1013
|
+
|
|
1014
|
+
// abort if user navigated during update
|
|
1015
|
+
if (token !== nav_token) return false;
|
|
1016
|
+
|
|
1017
|
+
if (navigation_result.type === 'redirect') {
|
|
1018
|
+
if (redirect_chain.length > 10 || redirect_chain.includes(url.pathname)) {
|
|
1019
|
+
navigation_result = await load_root_error_page({
|
|
1020
|
+
status: 500,
|
|
1021
|
+
error: await handle_error(new Error('Redirect loop'), {
|
|
1022
|
+
url,
|
|
1023
|
+
params: {},
|
|
1024
|
+
route: { id: null }
|
|
1025
|
+
}),
|
|
1026
|
+
url,
|
|
1027
|
+
route: { id: null }
|
|
1028
|
+
});
|
|
1029
|
+
} else {
|
|
1030
|
+
goto(
|
|
1031
|
+
new URL(navigation_result.location, url).href,
|
|
1032
|
+
{},
|
|
1033
|
+
[...redirect_chain, url.pathname],
|
|
1034
|
+
nav_token
|
|
1172
1035
|
);
|
|
1173
|
-
|
|
1036
|
+
return false;
|
|
1037
|
+
}
|
|
1038
|
+
} else if (/** @type {number} */ (navigation_result.props.page?.status) >= 400) {
|
|
1039
|
+
const updated = await stores.updated.check();
|
|
1040
|
+
if (updated) {
|
|
1041
|
+
await native_navigation(url);
|
|
1174
1042
|
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
// reset invalidation only after a finished navigation. If there are redirects or
|
|
1046
|
+
// additional invalidations, they should get the same invalidation treatment
|
|
1047
|
+
invalidated.length = 0;
|
|
1048
|
+
force_invalidation = false;
|
|
1049
|
+
|
|
1050
|
+
updating = true;
|
|
1051
|
+
|
|
1052
|
+
update_scroll_positions(previous_history_index);
|
|
1053
|
+
capture_snapshot(previous_history_index);
|
|
1054
|
+
|
|
1055
|
+
// ensure the url pathname matches the page's trailing slash option
|
|
1056
|
+
if (
|
|
1057
|
+
navigation_result.props.page?.url &&
|
|
1058
|
+
navigation_result.props.page.url.pathname !== url.pathname
|
|
1059
|
+
) {
|
|
1060
|
+
url.pathname = navigation_result.props.page?.url.pathname;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
if (details) {
|
|
1064
|
+
const change = details.replaceState ? 0 : 1;
|
|
1065
|
+
details.state[INDEX_KEY] = current_history_index += change;
|
|
1066
|
+
history[details.replaceState ? 'replaceState' : 'pushState'](details.state, '', url);
|
|
1067
|
+
|
|
1068
|
+
if (!details.replaceState) {
|
|
1069
|
+
// if we navigated back, then pushed a new state, we can
|
|
1070
|
+
// release memory by pruning the scroll/snapshot lookup
|
|
1071
|
+
let i = current_history_index + 1;
|
|
1072
|
+
while (snapshots[i] || scroll_positions[i]) {
|
|
1073
|
+
delete snapshots[i];
|
|
1074
|
+
delete scroll_positions[i];
|
|
1075
|
+
i += 1;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
// reset preload synchronously after the history state has been set to avoid race conditions
|
|
1081
|
+
load_cache = null;
|
|
1082
|
+
|
|
1083
|
+
if (started) {
|
|
1084
|
+
current = navigation_result.state;
|
|
1085
|
+
|
|
1086
|
+
// reset url before updating page store
|
|
1087
|
+
if (navigation_result.props.page) {
|
|
1088
|
+
navigation_result.props.page.url = url;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
root.$set(navigation_result.props);
|
|
1092
|
+
} else {
|
|
1093
|
+
initialize(navigation_result);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
const { activeElement } = document;
|
|
1097
|
+
|
|
1098
|
+
// need to render the DOM before we can scroll to the rendered elements and do focus management
|
|
1099
|
+
await tick();
|
|
1100
|
+
|
|
1101
|
+
// we reset scroll before dealing with focus, to avoid a flash of unscrolled content
|
|
1102
|
+
if (autoscroll) {
|
|
1103
|
+
const deep_linked =
|
|
1104
|
+
url.hash && document.getElementById(decodeURIComponent(url.hash.slice(1)));
|
|
1105
|
+
if (scroll) {
|
|
1106
|
+
scrollTo(scroll.x, scroll.y);
|
|
1107
|
+
} else if (deep_linked) {
|
|
1108
|
+
// Here we use `scrollIntoView` on the element instead of `scrollTo`
|
|
1109
|
+
// because it natively supports the `scroll-margin` and `scroll-behavior`
|
|
1110
|
+
// CSS properties.
|
|
1111
|
+
deep_linked.scrollIntoView();
|
|
1112
|
+
} else {
|
|
1113
|
+
scrollTo(0, 0);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
const changed_focus =
|
|
1118
|
+
// reset focus only if any manual focus management didn't override it
|
|
1119
|
+
document.activeElement !== activeElement &&
|
|
1120
|
+
// also refocus when activeElement is body already because the
|
|
1121
|
+
// focus event might not have been fired on it yet
|
|
1122
|
+
document.activeElement !== document.body;
|
|
1123
|
+
|
|
1124
|
+
if (!keepfocus && !changed_focus) {
|
|
1125
|
+
await reset_focus();
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
autoscroll = true;
|
|
1129
|
+
|
|
1130
|
+
if (navigation_result.props.page) {
|
|
1131
|
+
page = navigation_result.props.page;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
navigating = false;
|
|
1135
|
+
callbacks.after_navigate.forEach((fn) =>
|
|
1136
|
+
fn(/** @type {import('types').AfterNavigate} */ (navigation))
|
|
1175
1137
|
);
|
|
1138
|
+
stores.navigating.set(null);
|
|
1139
|
+
|
|
1140
|
+
updating = false;
|
|
1176
1141
|
}
|
|
1177
1142
|
|
|
1178
1143
|
/**
|
|
@@ -29,14 +29,12 @@ if (DEV) {
|
|
|
29
29
|
// We use just the filename as the method name sometimes does not appear on the CI.
|
|
30
30
|
const url = input instanceof Request ? input.url : input.toString();
|
|
31
31
|
const stack_array = /** @type {string} */ (new Error().stack).split('\n');
|
|
32
|
-
// We need to do
|
|
33
|
-
// across events and for example traces a `fetch` call triggered from a button
|
|
34
|
-
// to the creation of the event listener and the element creation itself,
|
|
32
|
+
// We need to do a cutoff because Safari and Firefox maintain the stack
|
|
33
|
+
// across events and for example traces a `fetch` call triggered from a button
|
|
34
|
+
// back to the creation of the event listener and the element creation itself,
|
|
35
35
|
// where at some point client.js will show up, leading to false positives.
|
|
36
|
-
const
|
|
37
|
-
const stack = stack_array
|
|
38
|
-
.slice(0, firefox_cutoff !== -1 ? firefox_cutoff : undefined)
|
|
39
|
-
.join('\n');
|
|
36
|
+
const cutoff = stack_array.findIndex((a) => a.includes('load@') || a.includes('at load'));
|
|
37
|
+
const stack = stack_array.slice(0, cutoff + 2).join('\n');
|
|
40
38
|
|
|
41
39
|
const heuristic = can_inspect_stack_trace
|
|
42
40
|
? stack.includes('src/runtime/client/client.js')
|
|
@@ -63,9 +63,9 @@ export async function render_response({
|
|
|
63
63
|
|
|
64
64
|
const { client } = manifest._;
|
|
65
65
|
|
|
66
|
-
const modulepreloads = new Set(
|
|
67
|
-
const stylesheets = new Set(client.
|
|
68
|
-
const fonts = new Set(client.
|
|
66
|
+
const modulepreloads = new Set(client.imports);
|
|
67
|
+
const stylesheets = new Set(client.stylesheets);
|
|
68
|
+
const fonts = new Set(client.fonts);
|
|
69
69
|
|
|
70
70
|
/** @type {Set<string>} */
|
|
71
71
|
const link_header_preloads = new Set();
|
|
@@ -292,10 +292,9 @@ export async function render_response({
|
|
|
292
292
|
const blocks = [];
|
|
293
293
|
|
|
294
294
|
const properties = [
|
|
295
|
-
`env: ${s(public_env)}`,
|
|
296
295
|
paths.assets && `assets: ${s(paths.assets)}`,
|
|
297
296
|
`base: ${base_expression}`,
|
|
298
|
-
`
|
|
297
|
+
`env: ${s(public_env)}`
|
|
299
298
|
].filter(Boolean);
|
|
300
299
|
|
|
301
300
|
if (chunks) {
|
|
@@ -318,7 +317,9 @@ export async function render_response({
|
|
|
318
317
|
${properties.join(',\n\t\t\t\t\t\t')}
|
|
319
318
|
};`);
|
|
320
319
|
|
|
321
|
-
const args = [`app`,
|
|
320
|
+
const args = [`app`, `element`];
|
|
321
|
+
|
|
322
|
+
blocks.push(`const element = document.currentScript.parentElement;`);
|
|
322
323
|
|
|
323
324
|
if (page_config.ssr) {
|
|
324
325
|
const serialized = { form: 'null', error: 'null' };
|
|
@@ -355,8 +356,8 @@ export async function render_response({
|
|
|
355
356
|
}
|
|
356
357
|
|
|
357
358
|
blocks.push(`Promise.all([
|
|
358
|
-
import(${s(prefixed(client.start
|
|
359
|
-
import(${s(prefixed(client.app
|
|
359
|
+
import(${s(prefixed(client.start))}),
|
|
360
|
+
import(${s(prefixed(client.app))})
|
|
360
361
|
]).then(([kit, app]) => {
|
|
361
362
|
kit.start(${args.join(', ')});
|
|
362
363
|
});`);
|
package/types/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
RouteSegment,
|
|
19
19
|
UniqueInterface
|
|
20
20
|
} from './private.js';
|
|
21
|
-
import {
|
|
21
|
+
import { BuildData, SSRNodeLoader, SSRRoute, ValidatedConfig } from './internal.js';
|
|
22
22
|
|
|
23
23
|
export { PrerenderOption } from './private.js';
|
|
24
24
|
|
|
@@ -1059,10 +1059,7 @@ export interface SSRManifest {
|
|
|
1059
1059
|
|
|
1060
1060
|
/** private fields */
|
|
1061
1061
|
_: {
|
|
1062
|
-
client:
|
|
1063
|
-
start: AssetDependencies;
|
|
1064
|
-
app: AssetDependencies;
|
|
1065
|
-
};
|
|
1062
|
+
client: NonNullable<BuildData['client']>;
|
|
1066
1063
|
nodes: SSRNodeLoader[];
|
|
1067
1064
|
routes: SSRRoute[];
|
|
1068
1065
|
matchers(): Promise<Record<string, ParamMatcher>>;
|
package/types/internal.d.ts
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
ResolveOptions,
|
|
11
11
|
Server,
|
|
12
12
|
ServerInitOptions,
|
|
13
|
-
SSRManifest,
|
|
14
13
|
HandleFetch,
|
|
15
14
|
Actions,
|
|
16
15
|
HandleClientError
|
|
@@ -55,8 +54,11 @@ export interface BuildData {
|
|
|
55
54
|
manifest_data: ManifestData;
|
|
56
55
|
service_worker: string | null;
|
|
57
56
|
client: {
|
|
58
|
-
start:
|
|
59
|
-
app:
|
|
57
|
+
start: string;
|
|
58
|
+
app: string;
|
|
59
|
+
imports: string[];
|
|
60
|
+
stylesheets: string[];
|
|
61
|
+
fonts: string[];
|
|
60
62
|
} | null;
|
|
61
63
|
server_manifest: import('vite').Manifest;
|
|
62
64
|
}
|