@sveltejs/kit 3.0.0-next.22 → 3.0.0-next.24
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 +40 -9
- package/src/cli.js +3 -3
- package/src/constants.js +13 -1
- package/src/core/adapt/builder.js +2 -3
- package/src/core/env.js +139 -181
- package/src/core/postbuild/analyse.js +9 -4
- package/src/core/postbuild/prerender.js +22 -23
- package/src/core/sync/create_manifest_data/index.js +29 -33
- package/src/core/sync/sync.js +23 -40
- package/src/core/sync/write_app_manifest.js +83 -0
- package/src/core/sync/write_client_manifest.js +6 -4
- package/src/core/sync/write_server.js +10 -6
- package/src/core/sync/write_types/index.js +2 -2
- package/src/core/utils.js +0 -28
- package/src/exports/hooks/public.d.ts +9 -1
- package/src/exports/index.js +10 -0
- package/src/exports/node/index.js +77 -5
- package/src/exports/public.d.ts +9 -0
- package/src/exports/vite/build/build_server.js +3 -3
- package/src/exports/vite/build/utils.js +48 -4
- package/src/exports/vite/dev/index.js +11 -22
- package/src/exports/vite/index.js +62 -345
- package/src/exports/vite/module_ids.js +1 -11
- package/src/exports/vite/plugins/env-vars.js +117 -0
- package/src/exports/vite/preview/index.js +6 -4
- package/src/exports/vite/utils.js +2 -4
- package/src/runtime/app/env/{types.d.ts → client.js} +9 -4
- package/src/runtime/app/env/index.js +1 -2
- package/src/runtime/app/env/private/index.js +1 -0
- package/src/runtime/app/env/public/client.js +1 -1
- package/src/runtime/app/env/public/server.js +1 -1
- package/src/runtime/app/env/{internal.js → server.js} +4 -4
- package/src/runtime/app/forms/client.js +263 -0
- package/src/runtime/app/forms/index.js +1 -263
- package/src/runtime/app/forms/public.d.ts +1 -1
- package/src/runtime/app/forms/server.js +6 -0
- package/src/runtime/app/forms/shared.js +34 -0
- package/src/runtime/app/manifest/index.js +1 -1
- package/src/runtime/app/navigation/client.js +15 -0
- package/src/runtime/app/navigation/index.js +1 -15
- package/src/runtime/app/navigation/public.d.ts +1 -1
- package/src/runtime/app/navigation/server.js +15 -0
- package/src/runtime/app/paths/server.js +1 -1
- package/src/runtime/app/server/public.d.ts +512 -0
- package/src/runtime/app/server/remote/command.js +1 -1
- package/src/runtime/app/server/remote/form.js +16 -6
- package/src/runtime/app/server/remote/prerender.js +2 -3
- package/src/runtime/app/server/remote/query.js +2 -2
- package/src/runtime/app/server/remote/requested.js +3 -3
- package/src/runtime/app/state/client.svelte.js +207 -0
- package/src/runtime/app/state/index.js +1 -66
- package/src/runtime/app/state/public.d.ts +1 -1
- package/src/runtime/client/bundle.js +1 -1
- package/src/runtime/client/client.js +206 -274
- package/src/runtime/client/fetcher.js +18 -8
- package/src/runtime/client/remote-functions/command.svelte.js +1 -1
- package/src/runtime/client/remote-functions/form.svelte.js +10 -7
- package/src/runtime/client/remote-functions/prerender.svelte.js +2 -2
- package/src/runtime/client/remote-functions/query/index.js +1 -1
- package/src/runtime/client/remote-functions/query/instance.svelte.js +2 -1
- package/src/runtime/client/remote-functions/query-batch.svelte.js +1 -1
- package/src/runtime/client/remote-functions/query-live/index.js +1 -1
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +4 -3
- package/src/runtime/client/remote-functions/query-live/iterator.js +1 -1
- package/src/runtime/client/remote-functions/shared.svelte.js +3 -3
- package/src/runtime/client/snapshots.js +1 -3
- package/src/runtime/client/stream.js +27 -20
- package/src/runtime/client/utils.js +7 -3
- package/src/runtime/components/root.svelte +5 -5
- package/src/runtime/env/dynamic/private.js +1 -1
- package/src/runtime/env/static/private.js +1 -1
- package/src/runtime/error-chain.js +54 -0
- package/src/runtime/form-utils.js +53 -77
- package/src/runtime/invalid-import.js +1 -0
- package/src/runtime/props.svelte.js +1 -1
- package/src/runtime/server/data/index.js +1 -1
- package/src/runtime/server/endpoint.js +8 -3
- package/src/runtime/server/env_module.js +1 -1
- package/src/runtime/server/errors.js +2 -2
- package/src/runtime/server/index.js +2 -2
- package/src/runtime/server/page/actions.js +77 -122
- package/src/runtime/server/page/index.js +37 -69
- package/src/runtime/server/page/render.js +18 -23
- package/src/runtime/server/remote-functions.js +15 -43
- package/src/runtime/server/respond.js +23 -3
- package/src/telemetry.js +1 -33
- package/src/types/ambient-private.d.ts +9 -17
- package/src/types/internal.d.ts +21 -5
- package/src/types/private.d.ts +1 -1
- package/src/utils/exports.js +1 -0
- package/src/utils/filesystem.js +9 -21
- package/src/utils/functions.js +10 -0
- package/src/utils/promise.js +25 -0
- package/src/utils/routing.js +0 -11
- package/src/utils/url.js +0 -11
- package/src/version.js +1 -1
- package/types/index.d.ts +1134 -1136
- package/types/index.d.ts.map +50 -50
- package/src/exports/remote/index.js +0 -11
- package/src/exports/remote/public.d.ts +0 -519
- package/src/runtime/app/env/private.js +0 -1
- package/src/runtime/app/env/standard-schema.d.ts +0 -0
- package/src/runtime/app/state/client.js +0 -63
- package/src/runtime/client/state.svelte.js +0 -98
- package/src/runtime/server/ambient.d.ts +0 -4
- package/src/utils/path.js +0 -23
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
/** @import { CacheEntry } from './remote-functions/cache.svelte.js' */
|
|
7
7
|
/** @import { Query } from './remote-functions/query/instance.svelte.js' */
|
|
8
8
|
/** @import { LiveQuery } from './remote-functions/query-live/instance.svelte.js' */
|
|
9
|
-
import {
|
|
9
|
+
import { DEV } from 'esm-env';
|
|
10
10
|
import { settled, tick, fork, onMount, hydrate, mount } from 'svelte';
|
|
11
11
|
import { HttpError, Redirect, SvelteKitError, HandledHttpError } from '@sveltejs/kit/internal';
|
|
12
12
|
import { decode_pathname, strip_hash, make_trackable, normalize_path } from '../../utils/url.js';
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
validate_load_response
|
|
51
51
|
} from '../shared.js';
|
|
52
52
|
|
|
53
|
-
import { page,
|
|
53
|
+
import { page, updated, notify_version, update_page, set_navigation } from '#app/state/client';
|
|
54
54
|
import { payload } from './payload.js';
|
|
55
55
|
import {
|
|
56
56
|
add_data_suffix,
|
|
@@ -62,6 +62,7 @@ import { read_ndjson } from './ndjson.js';
|
|
|
62
62
|
import Root from '../components/root.svelte';
|
|
63
63
|
import { Props, RenderNode } from '../props.svelte.js';
|
|
64
64
|
import { init_transport, parse, stringify } from '#app/internal/transport';
|
|
65
|
+
import { build_error_chain, nearest_error_pages } from '../error-chain.js';
|
|
65
66
|
|
|
66
67
|
/**
|
|
67
68
|
* @typedef {{
|
|
@@ -111,7 +112,7 @@ init_snapshots(() => (started && !is_navigating && !updating ? current_history_i
|
|
|
111
112
|
/** @type {Props} */
|
|
112
113
|
let props;
|
|
113
114
|
|
|
114
|
-
if (DEV
|
|
115
|
+
if (DEV) {
|
|
115
116
|
let warned = false;
|
|
116
117
|
|
|
117
118
|
const current_module_url = import.meta.url.split('?')[0]; // remove query params that vite adds to the URL when it is loaded from node_modules
|
|
@@ -472,6 +473,19 @@ export function start(_app, _target, data) {
|
|
|
472
473
|
return _start(_app, _target, data);
|
|
473
474
|
}
|
|
474
475
|
|
|
476
|
+
/**
|
|
477
|
+
* @template T
|
|
478
|
+
* @param {Map<string, Map<string, T>>} map
|
|
479
|
+
* @returns {Generator<[string, T]>} every entry of the cache map, keyed by remote key
|
|
480
|
+
*/
|
|
481
|
+
function* cache_entries(map) {
|
|
482
|
+
for (const [id, entries] of map) {
|
|
483
|
+
for (const [payload, entry] of entries) {
|
|
484
|
+
yield [create_remote_key(id, payload), entry];
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
475
489
|
/**
|
|
476
490
|
* @param {import('./types.js').SvelteKitApp} _app
|
|
477
491
|
* @param {HTMLElement} _target
|
|
@@ -518,12 +532,10 @@ async function _start(_app, _target, data) {
|
|
|
518
532
|
default_layout_loader = _app.nodes[0];
|
|
519
533
|
default_error_loader = _app.nodes[1];
|
|
520
534
|
|
|
521
|
-
const [root_layout
|
|
522
|
-
default_layout_loader(),
|
|
523
|
-
default_error_loader()
|
|
524
|
-
]);
|
|
535
|
+
const [root_layout] = await Promise.all([default_layout_loader(), default_error_loader()]);
|
|
525
536
|
|
|
526
|
-
|
|
537
|
+
// the root boundary stays unarmed: the root +error.svelte renders at the node below it
|
|
538
|
+
const tree = new RenderNode(root_layout.component, undefined);
|
|
527
539
|
|
|
528
540
|
props = new Props({
|
|
529
541
|
page,
|
|
@@ -616,19 +628,14 @@ async function _invalidate(reset_page_state = true) {
|
|
|
616
628
|
/** @type {Map<string, Promise<void>>} */
|
|
617
629
|
const live_query_reconnects = new Map();
|
|
618
630
|
if (force_invalidation) {
|
|
619
|
-
for (const
|
|
620
|
-
|
|
621
|
-
void resource.refresh();
|
|
622
|
-
}
|
|
631
|
+
for (const [, { resource }] of cache_entries(query_map)) {
|
|
632
|
+
void resource.refresh();
|
|
623
633
|
}
|
|
624
634
|
|
|
625
|
-
for (const [
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
promise.catch(noop);
|
|
630
|
-
live_query_reconnects.set(key, promise);
|
|
631
|
-
}
|
|
635
|
+
for (const [key, { resource }] of cache_entries(live_query_map)) {
|
|
636
|
+
const promise = resource.reconnect();
|
|
637
|
+
promise.catch(noop);
|
|
638
|
+
live_query_reconnects.set(key, promise);
|
|
632
639
|
}
|
|
633
640
|
}
|
|
634
641
|
|
|
@@ -654,30 +661,29 @@ async function _invalidate(reset_page_state = true) {
|
|
|
654
661
|
return;
|
|
655
662
|
}
|
|
656
663
|
|
|
657
|
-
|
|
664
|
+
apply_navigation_result(navigation_result);
|
|
665
|
+
|
|
666
|
+
// Preserve `page.state` when invalidating without resetting it (e.g. `refresh`/`refreshAll`).
|
|
667
|
+
// Must run after `apply_navigation_result`, which overwrites `state`/`shallow` with the fresh
|
|
668
|
+
// page object's `{}`/`null` values when the page changed.
|
|
658
669
|
if (!reset_page_state) {
|
|
659
|
-
|
|
670
|
+
update_page({ state: prev_state });
|
|
660
671
|
}
|
|
661
|
-
|
|
662
|
-
|
|
672
|
+
|
|
673
|
+
update_page({ shallow: prev_shallow });
|
|
663
674
|
current = { ...navigation_result.state, nav: current.nav };
|
|
664
675
|
reset_invalidation();
|
|
665
676
|
|
|
666
677
|
// only wait for promises that are connected to queries that still exist
|
|
667
678
|
/** @type {Promise<any>[]} */
|
|
668
679
|
const promises = [];
|
|
669
|
-
for (const
|
|
670
|
-
|
|
671
|
-
promises.push(resource);
|
|
672
|
-
}
|
|
680
|
+
for (const [, { resource }] of cache_entries(query_map)) {
|
|
681
|
+
promises.push(resource);
|
|
673
682
|
}
|
|
674
|
-
for (const [
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
if (promise) {
|
|
679
|
-
promises.push(promise);
|
|
680
|
-
}
|
|
683
|
+
for (const [key] of cache_entries(live_query_map)) {
|
|
684
|
+
const promise = live_query_reconnects.get(key);
|
|
685
|
+
if (promise) {
|
|
686
|
+
promises.push(promise);
|
|
681
687
|
}
|
|
682
688
|
}
|
|
683
689
|
|
|
@@ -764,20 +770,16 @@ export async function _goto(url, options = {}, redirect_count = 0, nav_token = {
|
|
|
764
770
|
if (options.refreshAll) {
|
|
765
771
|
force_invalidation = true;
|
|
766
772
|
query_keys = new Set();
|
|
767
|
-
for (const [
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
query_keys.add(create_remote_key(id, payload));
|
|
774
|
-
}
|
|
773
|
+
for (const [key, entry] of cache_entries(query_map)) {
|
|
774
|
+
// don't refresh yet, as some queries will be unrendered,
|
|
775
|
+
// but clear caches so that newly rendered queries
|
|
776
|
+
// don't use stale data. TODO same for `live_query_map`
|
|
777
|
+
entry.resource?.reset();
|
|
778
|
+
query_keys.add(key);
|
|
775
779
|
}
|
|
776
780
|
live_query_keys = new Set();
|
|
777
|
-
for (const [
|
|
778
|
-
|
|
779
|
-
live_query_keys.add(create_remote_key(id, payload));
|
|
780
|
-
}
|
|
781
|
+
for (const [key] of cache_entries(live_query_map)) {
|
|
782
|
+
live_query_keys.add(key);
|
|
781
783
|
}
|
|
782
784
|
}
|
|
783
785
|
|
|
@@ -793,18 +795,14 @@ export async function _goto(url, options = {}, redirect_count = 0, nav_token = {
|
|
|
793
795
|
void tick()
|
|
794
796
|
.then(tick)
|
|
795
797
|
.then(() => {
|
|
796
|
-
for (const [
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
void resource.start();
|
|
800
|
-
}
|
|
798
|
+
for (const [key, { resource }] of cache_entries(query_map)) {
|
|
799
|
+
if (query_keys?.has(key)) {
|
|
800
|
+
void resource.start();
|
|
801
801
|
}
|
|
802
802
|
}
|
|
803
|
-
for (const [
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
void resource.reconnect();
|
|
807
|
-
}
|
|
803
|
+
for (const [key, { resource }] of cache_entries(live_query_map)) {
|
|
804
|
+
if (live_query_keys?.has(key)) {
|
|
805
|
+
void resource.reconnect();
|
|
808
806
|
}
|
|
809
807
|
}
|
|
810
808
|
});
|
|
@@ -953,8 +951,7 @@ async function initialize(result, target, should_hydrate) {
|
|
|
953
951
|
props,
|
|
954
952
|
transformError: /** @param {unknown} e */ async (e) => {
|
|
955
953
|
const error = await handle_error(e, current.nav);
|
|
956
|
-
|
|
957
|
-
page.status = error.status;
|
|
954
|
+
update_page({ error, status: error.status });
|
|
958
955
|
return error;
|
|
959
956
|
}
|
|
960
957
|
});
|
|
@@ -1037,7 +1034,7 @@ async function get_navigation_result_from_branch({
|
|
|
1037
1034
|
route
|
|
1038
1035
|
},
|
|
1039
1036
|
props: {
|
|
1040
|
-
page,
|
|
1037
|
+
page: { ...page },
|
|
1041
1038
|
tree: /** @type {RenderNode} */ ({})
|
|
1042
1039
|
}
|
|
1043
1040
|
};
|
|
@@ -1053,7 +1050,12 @@ async function get_navigation_result_from_branch({
|
|
|
1053
1050
|
let data = {};
|
|
1054
1051
|
let data_changed = !page;
|
|
1055
1052
|
|
|
1053
|
+
const error_components =
|
|
1054
|
+
errors &&
|
|
1055
|
+
(await build_error_chain(branch, errors, (loader) => loader().then((e) => e.component)));
|
|
1056
|
+
|
|
1056
1057
|
let current_node = result.props.tree;
|
|
1058
|
+
let current_depth = 1;
|
|
1057
1059
|
|
|
1058
1060
|
/** @type {RenderNode | undefined} */
|
|
1059
1061
|
let previous_node = props.tree;
|
|
@@ -1089,12 +1091,9 @@ async function get_navigation_result_from_branch({
|
|
|
1089
1091
|
const next = branch[next_index];
|
|
1090
1092
|
|
|
1091
1093
|
if (next) {
|
|
1092
|
-
const error_loader =
|
|
1093
|
-
errors?.slice(0, next_index + 1).findLast((x) => x) ?? default_error_loader;
|
|
1094
|
-
|
|
1095
1094
|
current_node = current_node.child = new RenderNode(
|
|
1096
1095
|
next.node.component,
|
|
1097
|
-
|
|
1096
|
+
error_components?.[current_depth++]
|
|
1098
1097
|
);
|
|
1099
1098
|
|
|
1100
1099
|
previous_node = previous_node?.child;
|
|
@@ -1307,17 +1306,14 @@ async function load_node({ loader, parent, url, params, route, server_data_node
|
|
|
1307
1306
|
* @param {URL} url
|
|
1308
1307
|
*/
|
|
1309
1308
|
function resolve_fetch_url(input, init, url) {
|
|
1310
|
-
let requested = input instanceof Request ? input.url : input;
|
|
1311
|
-
|
|
1312
1309
|
// we must fixup relative urls so they are resolved from the target page
|
|
1313
|
-
const resolved = new URL(
|
|
1310
|
+
const resolved = new URL(input instanceof Request ? input.url : input, url);
|
|
1314
1311
|
|
|
1315
|
-
// match
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1312
|
+
// match the server's serialization of `fetched.url` (see load_data.js): a path for same-origin
|
|
1313
|
+
// urls, so prerendered pages can be served from any origin, the normalized href otherwise
|
|
1314
|
+
const requested =
|
|
1315
|
+
resolved.origin === url.origin ? resolved.href.slice(url.origin.length) : resolved.href;
|
|
1319
1316
|
|
|
1320
|
-
// prerendered pages may be served from any origin, so `initial_fetch` urls shouldn't be resolved
|
|
1321
1317
|
const promise = started
|
|
1322
1318
|
? subsequent_fetch(requested, resolved.href, init)
|
|
1323
1319
|
: initial_fetch(requested, init);
|
|
@@ -1385,12 +1381,12 @@ function diff_search_params(old_url, new_url) {
|
|
|
1385
1381
|
const changed = new Set([...old_url.searchParams.keys(), ...new_url.searchParams.keys()]);
|
|
1386
1382
|
|
|
1387
1383
|
for (const key of changed) {
|
|
1388
|
-
const old_values = old_url.searchParams.getAll(key);
|
|
1389
|
-
const new_values = new_url.searchParams.getAll(key);
|
|
1384
|
+
const old_values = old_url.searchParams.getAll(key).sort();
|
|
1385
|
+
const new_values = new_url.searchParams.getAll(key).sort();
|
|
1390
1386
|
|
|
1391
1387
|
if (
|
|
1392
|
-
old_values.
|
|
1393
|
-
|
|
1388
|
+
old_values.length === new_values.length &&
|
|
1389
|
+
old_values.every((value, i) => value === new_values[i])
|
|
1394
1390
|
) {
|
|
1395
1391
|
changed.delete(key);
|
|
1396
1392
|
}
|
|
@@ -1642,27 +1638,20 @@ async function load_route({ id, invalidating, url, params, route, preload, actio
|
|
|
1642
1638
|
* @param {number} i Start index to backtrack from
|
|
1643
1639
|
* @param {Array<import('./types.js').BranchNode | undefined>} branch Branch to backtrack
|
|
1644
1640
|
* @param {Array<import('types').CSRPageNodeLoader | undefined>} errors All error pages for this branch
|
|
1645
|
-
* @returns {Promise<
|
|
1641
|
+
* @returns {Promise<Array<import('./types.js').BranchNode | undefined> | undefined>} the branch truncated at the error page's depth
|
|
1646
1642
|
*/
|
|
1647
1643
|
async function load_nearest_error_page(i, branch, errors) {
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
server: null,
|
|
1660
|
-
universal: null
|
|
1661
|
-
}
|
|
1662
|
-
};
|
|
1663
|
-
} catch {
|
|
1664
|
-
continue;
|
|
1665
|
-
}
|
|
1644
|
+
for (const { error, idx } of nearest_error_pages(i, branch, errors)) {
|
|
1645
|
+
try {
|
|
1646
|
+
return branch.slice(0, idx).concat({
|
|
1647
|
+
node: await error(),
|
|
1648
|
+
loader: error,
|
|
1649
|
+
data: {},
|
|
1650
|
+
server: null,
|
|
1651
|
+
universal: null
|
|
1652
|
+
});
|
|
1653
|
+
} catch {
|
|
1654
|
+
continue;
|
|
1666
1655
|
}
|
|
1667
1656
|
}
|
|
1668
1657
|
}
|
|
@@ -1680,12 +1669,12 @@ async function load_nearest_error_page(i, branch, errors) {
|
|
|
1680
1669
|
* }} opts
|
|
1681
1670
|
*/
|
|
1682
1671
|
async function load_route_error({ i, branch, errors, error, status, url, params, route }) {
|
|
1683
|
-
const
|
|
1684
|
-
if (
|
|
1672
|
+
const error_branch = await load_nearest_error_page(i, branch, errors);
|
|
1673
|
+
if (error_branch) {
|
|
1685
1674
|
return get_navigation_result_from_branch({
|
|
1686
1675
|
url,
|
|
1687
1676
|
params,
|
|
1688
|
-
branch:
|
|
1677
|
+
branch: error_branch,
|
|
1689
1678
|
errors,
|
|
1690
1679
|
error,
|
|
1691
1680
|
status,
|
|
@@ -2038,48 +2027,34 @@ async function navigate({
|
|
|
2038
2027
|
is_navigating = true;
|
|
2039
2028
|
|
|
2040
2029
|
if (started && nav.navigation.type !== 'enter') {
|
|
2041
|
-
|
|
2030
|
+
set_navigation(nav.navigation);
|
|
2042
2031
|
}
|
|
2043
2032
|
|
|
2044
2033
|
let navigation_result = intent && (await load_route({ ...intent, action_result }));
|
|
2045
2034
|
|
|
2046
2035
|
if (!navigation_result) {
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
await handle_error(
|
|
2055
|
-
new SvelteKitError(
|
|
2056
|
-
404,
|
|
2057
|
-
'Not Found',
|
|
2058
|
-
`Not found: ${url.pathname} (did you forget the hash?)`
|
|
2059
|
-
),
|
|
2060
|
-
{
|
|
2061
|
-
url,
|
|
2062
|
-
params: {},
|
|
2063
|
-
route: { id: null }
|
|
2064
|
-
}
|
|
2065
|
-
),
|
|
2066
|
-
replace_state
|
|
2067
|
-
);
|
|
2068
|
-
} else {
|
|
2069
|
-
return await native_navigation(url, replace_state);
|
|
2070
|
-
}
|
|
2071
|
-
} else {
|
|
2072
|
-
navigation_result = await server_fallback(
|
|
2073
|
-
url,
|
|
2074
|
-
{ id: null },
|
|
2075
|
-
await handle_error(new SvelteKitError(404, 'Not Found', `Not found: ${url.pathname}`), {
|
|
2076
|
-
url,
|
|
2077
|
-
params: {},
|
|
2078
|
-
route: { id: null }
|
|
2079
|
-
}),
|
|
2080
|
-
replace_state
|
|
2081
|
-
);
|
|
2036
|
+
const external = is_external_url(url, base, app.hash);
|
|
2037
|
+
// Special case for hash mode during DEV: If someone accidentally forgets to use a hash for the link,
|
|
2038
|
+
// they would end up here in an endless loop. Fall back to error page in that case
|
|
2039
|
+
const missing_hash = external && DEV && app.hash;
|
|
2040
|
+
|
|
2041
|
+
if (external && !missing_hash) {
|
|
2042
|
+
return await native_navigation(url, replace_state);
|
|
2082
2043
|
}
|
|
2044
|
+
|
|
2045
|
+
navigation_result = await server_fallback(
|
|
2046
|
+
url,
|
|
2047
|
+
{ id: null },
|
|
2048
|
+
await handle_error(
|
|
2049
|
+
new SvelteKitError(
|
|
2050
|
+
404,
|
|
2051
|
+
'Not Found',
|
|
2052
|
+
`Not found: ${url.pathname}${missing_hash ? ' (did you forget the hash?)' : ''}`
|
|
2053
|
+
),
|
|
2054
|
+
{ url, params: {}, route: { id: null } }
|
|
2055
|
+
),
|
|
2056
|
+
replace_state
|
|
2057
|
+
);
|
|
2083
2058
|
}
|
|
2084
2059
|
|
|
2085
2060
|
// if this is an internal navigation intent, use the normalized
|
|
@@ -2205,26 +2180,7 @@ async function navigate({
|
|
|
2205
2180
|
*/
|
|
2206
2181
|
let commit_promise;
|
|
2207
2182
|
if (started) {
|
|
2208
|
-
|
|
2209
|
-
await Promise.all(
|
|
2210
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable -- we need to await because they can be asynchronous
|
|
2211
|
-
Array.from(on_navigate_callbacks, (fn) => fn(/** @type {OnNavigate} */ (nav.navigation)))
|
|
2212
|
-
)
|
|
2213
|
-
).filter(/** @returns {value is () => void} */ (value) => typeof value === 'function');
|
|
2214
|
-
|
|
2215
|
-
if (after_navigate.length > 0) {
|
|
2216
|
-
function cleanup() {
|
|
2217
|
-
after_navigate.forEach((fn) => {
|
|
2218
|
-
after_navigate_callbacks.delete(fn);
|
|
2219
|
-
});
|
|
2220
|
-
}
|
|
2221
|
-
|
|
2222
|
-
after_navigate.push(cleanup);
|
|
2223
|
-
|
|
2224
|
-
after_navigate.forEach((fn) => {
|
|
2225
|
-
after_navigate_callbacks.add(fn);
|
|
2226
|
-
});
|
|
2227
|
-
}
|
|
2183
|
+
await run_on_navigate_callbacks(/** @type {OnNavigate} */ (nav.navigation));
|
|
2228
2184
|
|
|
2229
2185
|
// Type-casts are save because we know this resolved a proper SvelteKit route
|
|
2230
2186
|
const target = popped?.shallow
|
|
@@ -2266,15 +2222,15 @@ async function navigate({
|
|
|
2266
2222
|
} else {
|
|
2267
2223
|
apply_navigation_result(navigation_result);
|
|
2268
2224
|
|
|
2269
|
-
// Reset
|
|
2270
|
-
//
|
|
2271
|
-
//
|
|
2272
|
-
|
|
2273
|
-
reset_boundary
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2225
|
+
// Reset boundaries that failed on a previous navigation once the new props have
|
|
2226
|
+
// flushed (see sveltejs/kit#15694). Resetting first re-renders the old content at
|
|
2227
|
+
// a depth the new tree may not have, stranding the stale `+error.svelte`.
|
|
2228
|
+
commit_promise = settled().then(() => {
|
|
2229
|
+
for (const reset_boundary of resetters) {
|
|
2230
|
+
reset_boundary();
|
|
2231
|
+
}
|
|
2232
|
+
resetters.clear();
|
|
2233
|
+
});
|
|
2278
2234
|
}
|
|
2279
2235
|
|
|
2280
2236
|
has_navigated = true;
|
|
@@ -2282,17 +2238,70 @@ async function navigate({
|
|
|
2282
2238
|
await initialize(navigation_result, target, false);
|
|
2283
2239
|
}
|
|
2284
2240
|
|
|
2285
|
-
const
|
|
2241
|
+
const finished = await finish_navigation(
|
|
2242
|
+
nav,
|
|
2243
|
+
nav_token,
|
|
2244
|
+
url,
|
|
2245
|
+
popped?.scroll,
|
|
2246
|
+
reset,
|
|
2247
|
+
commit_promise
|
|
2248
|
+
);
|
|
2249
|
+
if (!finished) return;
|
|
2286
2250
|
|
|
2287
|
-
|
|
2251
|
+
if (type === 'popstate') {
|
|
2252
|
+
restore_snapshot(current_navigation_index);
|
|
2253
|
+
}
|
|
2254
|
+
// new and replaced entries have no stored values, so this only resets there
|
|
2255
|
+
restore_navigation_snapshot(current_history_index, previous_snapshot_registrations);
|
|
2256
|
+
|
|
2257
|
+
set_navigation(null);
|
|
2258
|
+
|
|
2259
|
+
updating = false;
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
/**
|
|
2263
|
+
* Runs the `onNavigate` callbacks and registers any functions they return to run after the navigation
|
|
2264
|
+
* @param {OnNavigate} navigation
|
|
2265
|
+
*/
|
|
2266
|
+
async function run_on_navigate_callbacks(navigation) {
|
|
2267
|
+
const after_navigate = (
|
|
2268
|
+
await Promise.all(
|
|
2269
|
+
// eslint-disable-next-line @typescript-eslint/await-thenable -- we need to await because they can be asynchronous
|
|
2270
|
+
Array.from(on_navigate_callbacks, (fn) => fn(navigation))
|
|
2271
|
+
)
|
|
2272
|
+
).filter(/** @returns {value is () => void} */ (value) => typeof value === 'function');
|
|
2273
|
+
|
|
2274
|
+
if (after_navigate.length > 0) {
|
|
2275
|
+
function cleanup() {
|
|
2276
|
+
after_navigate.forEach((fn) => after_navigate_callbacks.delete(fn));
|
|
2277
|
+
}
|
|
2278
|
+
|
|
2279
|
+
after_navigate.push(cleanup);
|
|
2280
|
+
after_navigate.forEach((fn) => after_navigate_callbacks.add(fn));
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
/**
|
|
2285
|
+
* Settles the navigation once `updated` resolves. Returns `false` if a newer navigation
|
|
2286
|
+
* superseded it in the meantime, in which case the caller must stop
|
|
2287
|
+
* @param {ReturnType<typeof create_navigation>} nav
|
|
2288
|
+
* @param {{}} nav_token
|
|
2289
|
+
* @param {URL} url
|
|
2290
|
+
* @param {{ x: number, y: number } | null | undefined} popped_scroll the scroll position to restore for popstate navigations
|
|
2291
|
+
* @param {boolean} reset
|
|
2292
|
+
* @param {Promise<void> | undefined} updated
|
|
2293
|
+
*/
|
|
2294
|
+
async function finish_navigation(nav, nav_token, url, popped_scroll, reset, updated) {
|
|
2295
|
+
const active_element = document.activeElement;
|
|
2296
|
+
|
|
2297
|
+
await updated;
|
|
2288
2298
|
|
|
2289
2299
|
if (navigation_token !== nav_token) {
|
|
2290
|
-
// a new navigation happened while we were waiting for the DOM to update, so abort
|
|
2291
2300
|
nav.reject(new Error('navigation aborted'));
|
|
2292
|
-
return;
|
|
2301
|
+
return false;
|
|
2293
2302
|
}
|
|
2294
2303
|
|
|
2295
|
-
reset_scroll_and_focus(url, reset ?
|
|
2304
|
+
reset_scroll_and_focus(url, reset ? popped_scroll : scroll_state(), reset, active_element);
|
|
2296
2305
|
|
|
2297
2306
|
is_navigating = false;
|
|
2298
2307
|
|
|
@@ -2305,15 +2314,7 @@ async function navigate({
|
|
|
2305
2314
|
|
|
2306
2315
|
after_navigate_callbacks.forEach((fn) => fn(/** @type {AfterNavigate} */ (nav.navigation)));
|
|
2307
2316
|
|
|
2308
|
-
|
|
2309
|
-
restore_snapshot(current_navigation_index);
|
|
2310
|
-
}
|
|
2311
|
-
// new and replaced entries have no stored values, so this only resets there
|
|
2312
|
-
restore_navigation_snapshot(current_history_index, previous_snapshot_registrations);
|
|
2313
|
-
|
|
2314
|
-
navigating.current = null;
|
|
2315
|
-
|
|
2316
|
-
updating = false;
|
|
2317
|
+
return true;
|
|
2317
2318
|
}
|
|
2318
2319
|
|
|
2319
2320
|
/**
|
|
@@ -2611,10 +2612,6 @@ export function onNavigate(callback) {
|
|
|
2611
2612
|
* @returns {void}
|
|
2612
2613
|
*/
|
|
2613
2614
|
export function disableScrollHandling() {
|
|
2614
|
-
if (!BROWSER) {
|
|
2615
|
-
throw new Error('Cannot call disableScrollHandling() on the server');
|
|
2616
|
-
}
|
|
2617
|
-
|
|
2618
2615
|
if (DEV && started && !updating) {
|
|
2619
2616
|
throw new Error('Can only disable scroll handling during navigation');
|
|
2620
2617
|
}
|
|
@@ -2671,10 +2668,6 @@ async function resolve_intent(url, caller) {
|
|
|
2671
2668
|
* @returns {Promise<void>}
|
|
2672
2669
|
*/
|
|
2673
2670
|
export async function goto(url, opts = {}) {
|
|
2674
|
-
if (!BROWSER) {
|
|
2675
|
-
throw new Error('Cannot call goto(...) on the server');
|
|
2676
|
-
}
|
|
2677
|
-
|
|
2678
2671
|
if (DEV) {
|
|
2679
2672
|
if ('replaceState' in opts && !warned_on_replace_state) {
|
|
2680
2673
|
warned_on_replace_state = true;
|
|
@@ -2743,12 +2736,7 @@ export async function goto(url, opts = {}) {
|
|
|
2743
2736
|
* @returns {Promise<void>}
|
|
2744
2737
|
*/
|
|
2745
2738
|
export function invalidate(resource, keepState = false) {
|
|
2746
|
-
if (!BROWSER) {
|
|
2747
|
-
throw new Error('Cannot call invalidate(...) on the server');
|
|
2748
|
-
}
|
|
2749
|
-
|
|
2750
2739
|
push_invalidated(resource);
|
|
2751
|
-
|
|
2752
2740
|
return _invalidate(!keepState);
|
|
2753
2741
|
}
|
|
2754
2742
|
|
|
@@ -2773,10 +2761,6 @@ function push_invalidated(resource) {
|
|
|
2773
2761
|
* @returns {Promise<void>}
|
|
2774
2762
|
*/
|
|
2775
2763
|
export function invalidateAll() {
|
|
2776
|
-
if (!BROWSER) {
|
|
2777
|
-
throw new Error('Cannot call invalidateAll() on the server');
|
|
2778
|
-
}
|
|
2779
|
-
|
|
2780
2764
|
force_invalidation = true;
|
|
2781
2765
|
return _invalidate();
|
|
2782
2766
|
}
|
|
@@ -2787,10 +2771,6 @@ export function invalidateAll() {
|
|
|
2787
2771
|
* @returns {Promise<void>}
|
|
2788
2772
|
*/
|
|
2789
2773
|
export function refreshAll() {
|
|
2790
|
-
if (!BROWSER) {
|
|
2791
|
-
throw new Error('Cannot call refreshAll() on the server');
|
|
2792
|
-
}
|
|
2793
|
-
|
|
2794
2774
|
force_invalidation = true;
|
|
2795
2775
|
return _invalidate(false);
|
|
2796
2776
|
}
|
|
@@ -2808,10 +2788,6 @@ export function refreshAll() {
|
|
|
2808
2788
|
* @returns {Promise<({ type: 'loaded'; data: Record<string, any> } | { type: 'redirect'; location: string } | { type: 'error'; error: App.Error }) & { status: number; }>}
|
|
2809
2789
|
*/
|
|
2810
2790
|
export async function preloadData(href) {
|
|
2811
|
-
if (!BROWSER) {
|
|
2812
|
-
throw new Error('Cannot call preloadData(...) on the server');
|
|
2813
|
-
}
|
|
2814
|
-
|
|
2815
2791
|
const url = resolve_url(href);
|
|
2816
2792
|
const intent = await get_navigation_intent(url, false);
|
|
2817
2793
|
|
|
@@ -2872,10 +2848,6 @@ export async function preloadData(href) {
|
|
|
2872
2848
|
* @returns {Promise<void>}
|
|
2873
2849
|
*/
|
|
2874
2850
|
export async function preloadCode(id) {
|
|
2875
|
-
if (!BROWSER) {
|
|
2876
|
-
throw new Error('Cannot call preloadCode(...) on the server');
|
|
2877
|
-
}
|
|
2878
|
-
|
|
2879
2851
|
if (DEV && id[0] !== '/') {
|
|
2880
2852
|
throw new Error(
|
|
2881
2853
|
`argument passed to preloadCode must be a route ID (i.e. "/blog/[slug]" rather than "blog/[slug]")`
|
|
@@ -2933,10 +2905,6 @@ export async function preloadCode(id) {
|
|
|
2933
2905
|
* @returns {Promise<void>}
|
|
2934
2906
|
*/
|
|
2935
2907
|
export async function pushState(url, state) {
|
|
2936
|
-
if (!BROWSER) {
|
|
2937
|
-
throw new Error('Cannot call pushState(...) on the server');
|
|
2938
|
-
}
|
|
2939
|
-
|
|
2940
2908
|
if (DEV && !warned_on_push_state) {
|
|
2941
2909
|
warned_on_push_state = true;
|
|
2942
2910
|
console.warn(
|
|
@@ -2963,10 +2931,6 @@ export async function pushState(url, state) {
|
|
|
2963
2931
|
* @returns {Promise<void>}
|
|
2964
2932
|
*/
|
|
2965
2933
|
export async function replaceState(url, state) {
|
|
2966
|
-
if (!BROWSER) {
|
|
2967
|
-
throw new Error('Cannot call replaceState(...) on the server');
|
|
2968
|
-
}
|
|
2969
|
-
|
|
2970
2934
|
if (DEV && !warned_on_replace_state_function) {
|
|
2971
2935
|
warned_on_replace_state_function = true;
|
|
2972
2936
|
console.warn(
|
|
@@ -3009,7 +2973,7 @@ async function update_state(intent, state, { replace, persist_state, reset }, ca
|
|
|
3009
2973
|
if (nav) {
|
|
3010
2974
|
navigation_token = invalidation_token = nav_token;
|
|
3011
2975
|
is_navigating = true;
|
|
3012
|
-
|
|
2976
|
+
set_navigation(nav.navigation);
|
|
3013
2977
|
updating = true;
|
|
3014
2978
|
}
|
|
3015
2979
|
|
|
@@ -3046,59 +3010,29 @@ async function update_state(intent, state, { replace, persist_state, reset }, ca
|
|
|
3046
3010
|
}
|
|
3047
3011
|
|
|
3048
3012
|
if (nav) {
|
|
3049
|
-
|
|
3050
|
-
await Promise.all(
|
|
3051
|
-
// eslint-disable-next-line @typescript-eslint/await-thenable -- we need to await because they can be asynchronous
|
|
3052
|
-
Array.from(on_navigate_callbacks, (fn) => fn(/** @type {OnNavigate} */ (nav.navigation)))
|
|
3053
|
-
)
|
|
3054
|
-
).filter(/** @returns {value is () => void} */ (value) => typeof value === 'function');
|
|
3055
|
-
|
|
3056
|
-
if (after_navigate.length > 0) {
|
|
3057
|
-
function cleanup() {
|
|
3058
|
-
after_navigate.forEach((fn) => after_navigate_callbacks.delete(fn));
|
|
3059
|
-
}
|
|
3060
|
-
|
|
3061
|
-
after_navigate.push(cleanup);
|
|
3062
|
-
after_navigate.forEach((fn) => after_navigate_callbacks.add(fn));
|
|
3063
|
-
}
|
|
3013
|
+
await run_on_navigate_callbacks(/** @type {OnNavigate} */ (nav.navigation));
|
|
3064
3014
|
}
|
|
3065
3015
|
|
|
3066
3016
|
blur_active_element(reset);
|
|
3067
3017
|
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
if (nav) {
|
|
3076
|
-
const { activeElement } = document;
|
|
3077
|
-
|
|
3078
|
-
await settled();
|
|
3079
|
-
|
|
3080
|
-
if (navigation_token !== nav_token) {
|
|
3081
|
-
// a new navigation happened while we were waiting for the DOM to update, so abort
|
|
3082
|
-
nav.reject(new Error('navigation aborted'));
|
|
3083
|
-
return;
|
|
3084
|
-
}
|
|
3085
|
-
|
|
3086
|
-
reset_scroll_and_focus(url, reset ? null : scroll_state(), reset, activeElement);
|
|
3087
|
-
|
|
3088
|
-
is_navigating = false;
|
|
3089
|
-
nav.fulfil(undefined);
|
|
3090
|
-
|
|
3091
|
-
if (nav.navigation.to) {
|
|
3092
|
-
nav.navigation.to.scroll = scroll_state();
|
|
3018
|
+
update_page({
|
|
3019
|
+
state,
|
|
3020
|
+
shallow: {
|
|
3021
|
+
params: intent?.params ?? null,
|
|
3022
|
+
route: intent ? { id: intent.route.id } : null,
|
|
3023
|
+
url
|
|
3093
3024
|
}
|
|
3025
|
+
});
|
|
3094
3026
|
|
|
3095
|
-
|
|
3027
|
+
if (nav) {
|
|
3028
|
+
const finished = await finish_navigation(nav, nav_token, url, null, reset, settled());
|
|
3029
|
+
if (!finished) return;
|
|
3096
3030
|
}
|
|
3097
3031
|
|
|
3098
3032
|
restore_navigation_snapshot(current_history_index, previous_snapshot_registrations);
|
|
3099
3033
|
|
|
3100
3034
|
if (nav) {
|
|
3101
|
-
|
|
3035
|
+
set_navigation(null);
|
|
3102
3036
|
updating = false;
|
|
3103
3037
|
}
|
|
3104
3038
|
}
|
|
@@ -3113,10 +3047,6 @@ async function update_state(intent, state, { replace, persist_state, reset }, ca
|
|
|
3113
3047
|
* @returns {Promise<void>}
|
|
3114
3048
|
*/
|
|
3115
3049
|
export async function applyAction(result) {
|
|
3116
|
-
if (!BROWSER) {
|
|
3117
|
-
throw new Error('Cannot call applyAction(...) on the server');
|
|
3118
|
-
}
|
|
3119
|
-
|
|
3120
3050
|
if (result.type === 'redirect') {
|
|
3121
3051
|
await _goto(result.location, { refreshAll: true });
|
|
3122
3052
|
return;
|
|
@@ -3125,8 +3055,10 @@ export async function applyAction(result) {
|
|
|
3125
3055
|
if (result.type === 'error') {
|
|
3126
3056
|
await set_nearest_error_page(result.error);
|
|
3127
3057
|
} else {
|
|
3128
|
-
|
|
3129
|
-
|
|
3058
|
+
update_page({
|
|
3059
|
+
form: result.data,
|
|
3060
|
+
status: result.status
|
|
3061
|
+
});
|
|
3130
3062
|
|
|
3131
3063
|
/** @type {Record<string, any>} */
|
|
3132
3064
|
// this brings Svelte's view of the world in line with SvelteKit's
|
|
@@ -3197,14 +3129,14 @@ export async function set_nearest_error_page(error) {
|
|
|
3197
3129
|
const { branch, route } = current;
|
|
3198
3130
|
if (!route) return;
|
|
3199
3131
|
|
|
3200
|
-
const
|
|
3201
|
-
if (
|
|
3132
|
+
const error_branch = await load_nearest_error_page(current.branch.length, branch, route.errors);
|
|
3133
|
+
if (error_branch) {
|
|
3202
3134
|
const navigation_result = await get_navigation_result_from_branch({
|
|
3203
3135
|
url,
|
|
3204
3136
|
params: current.params,
|
|
3205
|
-
branch:
|
|
3137
|
+
branch: error_branch,
|
|
3206
3138
|
error,
|
|
3207
|
-
|
|
3139
|
+
errors: route.errors,
|
|
3208
3140
|
route
|
|
3209
3141
|
});
|
|
3210
3142
|
|
|
@@ -3491,11 +3423,10 @@ function _start_router() {
|
|
|
3491
3423
|
|
|
3492
3424
|
blur_active_element(reset);
|
|
3493
3425
|
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
page.shallow = shallow_target;
|
|
3426
|
+
update_page({
|
|
3427
|
+
state,
|
|
3428
|
+
shallow: shallow_target
|
|
3429
|
+
});
|
|
3499
3430
|
|
|
3500
3431
|
update_url(url);
|
|
3501
3432
|
|
|
@@ -3584,7 +3515,7 @@ function _start_router() {
|
|
|
3584
3515
|
// the navigation away from it was successful.
|
|
3585
3516
|
// Info about bfcache here: https://web.dev/bfcache
|
|
3586
3517
|
if (event.persisted) {
|
|
3587
|
-
|
|
3518
|
+
set_navigation(null);
|
|
3588
3519
|
}
|
|
3589
3520
|
});
|
|
3590
3521
|
|
|
@@ -3592,7 +3523,8 @@ function _start_router() {
|
|
|
3592
3523
|
* @param {URL} url
|
|
3593
3524
|
*/
|
|
3594
3525
|
function update_url(url) {
|
|
3595
|
-
current.url =
|
|
3526
|
+
current.url = url;
|
|
3527
|
+
update_page({ url });
|
|
3596
3528
|
}
|
|
3597
3529
|
}
|
|
3598
3530
|
|
|
@@ -4061,7 +3993,7 @@ if (DEV) {
|
|
|
4061
3993
|
* @param {NavigationFinished} result
|
|
4062
3994
|
*/
|
|
4063
3995
|
function apply_navigation_result(result) {
|
|
4064
|
-
|
|
3996
|
+
update_page(result.props.page);
|
|
4065
3997
|
|
|
4066
3998
|
props.tree.data = result.props.tree.data;
|
|
4067
3999
|
props.tree.child = result.props.tree.child;
|