Skip to content

Commit f91fd47

Browse files
authored
feat: forking (#14793)
* feat: forking * remove log * tweak * bump * fixes * changeset * bail if load_cache was already discarded
1 parent 1f6fb19 commit f91fd47

File tree

4 files changed

+197
-217
lines changed

4 files changed

+197
-217
lines changed

.changeset/tough-cobras-say.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': minor
3+
---
4+
5+
feat: use experimental `fork` API when available

packages/kit/src/runtime/client/client.js

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,14 @@ const invalidated = [];
206206
*/
207207
const components = [];
208208

209-
/** @type {{id: string, token: {}, promise: Promise<import('./types.js').NavigationResult>} | null} */
209+
/** @type {{id: string, token: {}, promise: Promise<import('./types.js').NavigationResult>, fork: Promise<import('svelte').Fork | null> | null} | null} */
210210
let load_cache = null;
211211

212+
function discard_load_cache() {
213+
void load_cache?.fork?.then((f) => f?.discard());
214+
load_cache = null;
215+
}
216+
212217
/**
213218
* @type {Map<string, Promise<URL>>}
214219
* Cache for client-side rerouting, since it could contain async calls which we want to
@@ -382,7 +387,7 @@ async function _invalidate(include_load_functions = true, reset_page_state = tru
382387
// Also solves an edge case where a preload is triggered, the navigation for it
383388
// was then triggered and is still running while the invalidation kicks in,
384389
// at which point the invalidation should take over and "win".
385-
load_cache = null;
390+
discard_load_cache();
386391

387392
// Rerun queries
388393
if (force_invalidation) {
@@ -461,7 +466,7 @@ export async function _goto(url, options, redirect_count, nav_token) {
461466
// Clear preload cache when invalidateAll is true to ensure fresh data
462467
// after form submissions or explicit invalidations
463468
if (options.invalidateAll) {
464-
load_cache = null;
469+
discard_load_cache();
465470
}
466471

467472
await navigate({
@@ -518,11 +523,32 @@ async function _preload_data(intent) {
518523
preload_tokens.delete(preload);
519524
if (result.type === 'loaded' && result.state.error) {
520525
// Don't cache errors, because they might be transient
521-
load_cache = null;
526+
discard_load_cache();
522527
}
523528
return result;
524-
})
529+
}),
530+
fork: null
525531
};
532+
533+
if (svelte.fork) {
534+
const lc = load_cache;
535+
536+
lc.fork = lc.promise.then((result) => {
537+
// if load_cache was discarded before load_cache.promise could
538+
// resolve, bail rather than creating an orphan fork
539+
if (lc === load_cache && result.type === 'loaded') {
540+
try {
541+
return svelte.fork(() => {
542+
root.$set(result.props);
543+
});
544+
} catch {
545+
// if it errors, it's because the experimental flag isn't enabled
546+
}
547+
}
548+
549+
return null;
550+
});
551+
}
526552
}
527553

528554
return load_cache.promise;
@@ -1658,6 +1684,7 @@ async function navigate({
16581684
}
16591685

16601686
// reset preload synchronously after the history state has been set to avoid race conditions
1687+
const load_cache_fork = load_cache?.fork;
16611688
load_cache = null;
16621689

16631690
navigation_result.props.page.state = state;
@@ -1692,7 +1719,14 @@ async function navigate({
16921719
navigation_result.props.page.url = url;
16931720
}
16941721

1695-
root.$set(navigation_result.props);
1722+
const fork = load_cache_fork && (await load_cache_fork);
1723+
1724+
if (fork) {
1725+
void fork.commit();
1726+
} else {
1727+
root.$set(navigation_result.props);
1728+
}
1729+
16961730
update(navigation_result.props.page);
16971731
has_navigated = true;
16981732
} else {

0 commit comments

Comments
 (0)