Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
65f63d1
WIP
Rich-Harris Dec 10, 2024
e1d3d60
most existing stuff working
Rich-Harris Dec 10, 2024
46a1fb5
working
Rich-Harris Dec 10, 2024
e030e0c
paperwork
Rich-Harris Dec 10, 2024
af4a6a5
get $app/state working
Rich-Harris Dec 10, 2024
57033e2
prettier
Rich-Harris Dec 10, 2024
0ce95fc
stopgap
Rich-Harris Dec 10, 2024
67eda04
this seems to work
Rich-Harris Dec 11, 2024
e3cf558
update most of the test files
dummdidumm Dec 12, 2024
41702b0
fix
dummdidumm Dec 12, 2024
621464e
oops
dummdidumm Dec 13, 2024
53b464a
navigating
dummdidumm Dec 13, 2024
6086310
whitespace is important for our test assertion
dummdidumm Dec 13, 2024
eb4333f
fix
dummdidumm Dec 13, 2024
55bd262
adjust new tests/folder names, keep around old $app/stores-specific t…
dummdidumm Dec 13, 2024
33ede71
adjust test
dummdidumm Dec 13, 2024
ffa41ea
updated
dummdidumm Dec 13, 2024
21946bf
docs
dummdidumm Dec 13, 2024
a42e9ee
better dev time errors
dummdidumm Dec 13, 2024
75e80bc
another test
dummdidumm Dec 13, 2024
2d91ae9
adjust documentation
dummdidumm Dec 13, 2024
d23e821
nomenclature
dummdidumm Dec 13, 2024
490be47
lint
dummdidumm Dec 13, 2024
451f23f
adjust test name
dummdidumm Dec 13, 2024
dcade6d
oops
dummdidumm Dec 13, 2024
96db243
changeset
dummdidumm Dec 13, 2024
147447f
Merge branch 'main' into app-state
dummdidumm Dec 13, 2024
945e912
deprecate $app/stores
dummdidumm Dec 13, 2024
7fe7b62
fix hash link + typo
dummdidumm Dec 14, 2024
13d61a9
Update documentation/docs/60-appendix/40-migrating.md
Rich-Harris Dec 16, 2024
29f0b9c
fix/tweak
dummdidumm Dec 14, 2024
e223477
typos
dummdidumm Dec 16, 2024
7e31a4f
document deprecation, link between state/stores
Rich-Harris Dec 16, 2024
81f7dd1
Apply suggestions from code review
Rich-Harris Dec 16, 2024
687da67
regenerate
dummdidumm Dec 16, 2024
3b5ce2d
tweak wording
Rich-Harris Dec 16, 2024
fe06408
Merge branch 'app-state' of github.com:sveltejs/kit into app-state
Rich-Harris Dec 16, 2024
cf41f7e
small tweaks
Rich-Harris Dec 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/kit/scripts/generate-dts.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ await createBundle({
'$app/navigation': 'src/runtime/app/navigation.js',
'$app/paths': 'src/runtime/app/paths/types.d.ts',
'$app/server': 'src/runtime/app/server/index.js',
'$app/state': 'src/runtime/app/state/client.js',
'$app/stores': 'src/runtime/app/stores.js'
},
include: ['src']
Expand Down
29 changes: 29 additions & 0 deletions packages/kit/src/runtime/app/state/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { page as _page } from '../../client/state.svelte.js';

/** @type {import('@sveltejs/kit').Page} */
export const page = {
get data() {
return _page.data;
},
get error() {
return _page.error;
},
get form() {
return _page.form;
},
get params() {
return _page.params;
},
get route() {
return _page.route;
},
get state() {
return _page.state;
},
get status() {
return _page.status;
},
get url() {
return _page.url;
}
};
9 changes: 9 additions & 0 deletions packages/kit/src/runtime/app/state/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "module",
"exports": {
".": {
"browser": "./client.js",
"default": "./server.js"
}
}
}
32 changes: 32 additions & 0 deletions packages/kit/src/runtime/app/state/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { getContext } from 'svelte';

function context() {
return getContext('__request__');
}

export const page = {
get data() {
return context().page.data;
},
get error() {
return context().page.error;
},
get form() {
return context().page.form;
},
get params() {
return context().page.params;
},
get route() {
return context().page.route;
},
get state() {
return context().page.state;
},
get status() {
return context().page.status;
},
get url() {
return context().page.url;
}
};
35 changes: 24 additions & 11 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { HttpError, Redirect, SvelteKitError } from '../control.js';
import { INVALIDATED_PARAM, TRAILING_SLASH_PARAM, validate_depends } from '../shared.js';
import { get_message, get_status } from '../../utils/error.js';
import { writable } from 'svelte/store';
import { page, update } from './state.svelte.js';

const ICON_REL_ATTRIBUTES = new Set(['icon', 'shortcut icon', 'apple-touch-icon']);

Expand Down Expand Up @@ -228,9 +229,6 @@ let current_history_index;
/** @type {number} */
let current_navigation_index;

/** @type {import('@sveltejs/kit').Page} */
let page;

/** @type {{}} */
let token;

Expand Down Expand Up @@ -338,11 +336,12 @@ async function _invalidate() {
}

if (navigation_result.props.page) {
page = navigation_result.props.page;
Object.assign(page, navigation_result.props.page);
}
current = navigation_result.state;
reset_invalidation();
root.$set(navigation_result.props);
update(navigation_result.props.page);
}

function reset_invalidation() {
Expand Down Expand Up @@ -444,7 +443,7 @@ function initialize(result, target, hydrate) {
const style = document.querySelector('style[data-sveltekit]');
if (style) style.remove();

page = /** @type {import('@sveltejs/kit').Page} */ (result.props.page);
Object.assign(page, /** @type {import('@sveltejs/kit').Page} */ (result.props.page));

root = new app.root({
target,
Expand Down Expand Up @@ -1420,6 +1419,7 @@ async function navigate({
}

root.$set(navigation_result.props);
update(navigation_result.props.page);
has_navigated = true;
} else {
initialize(navigation_result, target, false);
Expand Down Expand Up @@ -1461,7 +1461,7 @@ async function navigate({
autoscroll = true;

if (navigation_result.props.page) {
page = navigation_result.props.page;
Object.assign(page, navigation_result.props.page);
}

navigating = false;
Expand Down Expand Up @@ -1903,7 +1903,7 @@ export function pushState(url, state) {
history.pushState(opts, '', resolve_url(url));
has_navigated = true;

page = { ...page, state };
page.state = state;
root.$set({ page });

clear_onward_history(current_history_index, current_navigation_index);
Expand Down Expand Up @@ -1944,7 +1944,7 @@ export function replaceState(url, state) {

history.replaceState(opts, '', resolve_url(url));

page = { ...page, state };
page.state = state;
root.$set({ page });
}

Expand Down Expand Up @@ -1981,18 +1981,22 @@ export async function applyAction(result) {
current = navigation_result.state;

root.$set(navigation_result.props);
update(navigation_result.props.page);

tick().then(reset_focus);
}
} else if (result.type === 'redirect') {
_goto(result.location, { invalidateAll: true }, 0);
} else {
page.form = result.data;
page.status = result.status;

/** @type {Record<string, any>} */
root.$set({
// this brings Svelte's view of the world in line with SvelteKit's
// after use:enhance reset the form....
form: null,
page: { ...page, form: result.data, status: result.status }
page
});

// ...so that setting the `form` prop takes effect and isn't ignored
Expand Down Expand Up @@ -2250,7 +2254,7 @@ function _start_router() {
if (scroll) scrollTo(scroll.x, scroll.y);

if (state !== page.state) {
page = { ...page, state };
page.state = state;
root.$set({ page });
}

Expand Down Expand Up @@ -2329,7 +2333,16 @@ function _start_router() {
*/
function update_url(url) {
current.url = url;
stores.page.set({ ...page, url });
stores.page.set({
data: page.data,
error: page.error,
form: page.form,
params: page.params,
route: page.route,
state: page.state,
status: page.status,
url
});
stores.page.notify();
}
}
Expand Down
39 changes: 39 additions & 0 deletions packages/kit/src/runtime/client/state.svelte.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { onMount } from 'svelte';

/** @type {import('@sveltejs/kit').Page} */
export let page;

// this is a bootleg way to tell if we're in old svelte or new svelte
const is_legacy =
onMount.toString().includes('$$') || /function \w+\(\) \{\}/.test(onMount.toString());

if (is_legacy) {
page = {
data: {},
form: null,
error: null,
params: {},
route: { id: null },
state: {},
status: -1,
url: new URL('https://example.com')
};
} else {
page = new (class Page {
data = $state.raw({});
form = $state.raw(null);
error = $state.raw(null);
params = $state.raw({});
route = $state.raw({ id: null });
state = $state.raw({});
status = $state.raw(-1);
url = $state.raw(new URL('https://example.com'));
})();
}

/**
* @param {import('@sveltejs/kit').Page} new_page
*/
export function update(new_page) {
Object.assign(page, new_page);
}
6 changes: 3 additions & 3 deletions packages/kit/src/runtime/components/svelte-5/error.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script>
import { page } from '$app/stores';
import { page } from '$app/state';
</script>

<h1>{$page.status}</h1>
<p>{$page.error?.message}</p>
<h1>{page.status}</h1>
<p>{page.error?.message}</p>
15 changes: 13 additions & 2 deletions packages/kit/src/runtime/server/page/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,17 @@ export async function render_response({
// portable as possible, but reset afterwards
if (paths.relative) paths.override({ base, assets });

const render_opts = {
context: new Map([
[
'__request__',
{
page: props.page
}
]
])
};

if (__SVELTEKIT_DEV__) {
const fetch = globalThis.fetch;
let warned = false;
Expand All @@ -168,14 +179,14 @@ export async function render_response({
};

try {
rendered = options.root.render(props);
rendered = options.root.render(props, render_opts);
} finally {
globalThis.fetch = fetch;
paths.reset();
}
} else {
try {
rendered = options.root.render(props);
rendered = options.root.render(props, render_opts);
} finally {
paths.reset();
}
Expand Down
5 changes: 4 additions & 1 deletion packages/kit/src/types/internal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,10 @@ export interface ServerMetadata {

export interface SSRComponent {
default: {
render(props: Record<string, any>): {
render(
props: Record<string, any>,
opts: { context: Map<any, any> }
): {
html: string;
head: string;
css: {
Expand Down
4 changes: 2 additions & 2 deletions packages/kit/test/apps/amp/src/routes/origin/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script>
import { page } from '$app/stores';
import { page } from '$app/state';

/** @type {import('./$types').PageData} */
export let data;
</script>

<p data-source="load">{data.origin}</p>
<p data-source="store">{$page.url.origin}</p>
<p data-source="store">{page.url.origin}</p>
<p data-source="endpoint">{data.data.origin}</p>
8 changes: 4 additions & 4 deletions packages/kit/test/apps/basics/src/routes/+error.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<script>
import { page } from '$app/stores';
import { page } from '$app/state';
</script>

<svelte:head>
<title>Custom error page: {$page.error.message}</title>
<title>Custom error page: {page.error.message}</title>
</svelte:head>

<h1>{$page.status}</h1>
<h1>{page.status}</h1>

<p id="message">This is your custom error page saying: "<b>{$page.error.message}</b>"</p>
<p id="message">This is your custom error page saying: "<b>{page.error.message}</b>"</p>

<style>
h1,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script>
import { enhance } from '$app/forms';
import { page } from '$app/stores';
import { page } from '$app/state';

/** @type {import('./$types').ActionData} */
export let form;
Expand All @@ -13,10 +13,10 @@
let count = 0;
</script>

<pre class="data1">prop: {data.enhance_counter}, store: {$page.data.enhance_counter}</pre>
<pre class="data1">prop: {data.enhance_counter}, store: {page.data.enhance_counter}</pre>

<pre class="formdata1">{JSON.stringify(form)}</pre>
<pre class="formdata2">{JSON.stringify($page.form)}</pre>
<pre class="formdata2">{JSON.stringify(page.form)}</pre>

<form method="post" action="?/login" use:enhance>
<input type="hidden" name="action" value="DOM clobbering" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
import { page } from '$app/stores';
import { page } from '$app/state';
</script>

<pre style:color="red">{$page.error?.message}</pre>
<pre style:color="red">{page.error?.message}</pre>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
import { page } from '$app/stores';
import { page } from '$app/state';
</script>

<h1>@{$page.params.username}</h1>
<h1>@{page.params.username}</h1>
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script>
import { page } from '$app/stores';
import { page } from '$app/state';

/** @type {import('./$types').PageData} */
export let data;
</script>

<h1>dynamic</h1>
<h2>{data.path}: {data.slug}</h2>
<h3>{$page.url.pathname}: {$page.params.slug}</h3>
<h3>{page.url.pathname}: {page.params.slug}</h3>
Loading
Loading