diff --git a/.changeset/quiet-lobsters-agree.md b/.changeset/quiet-lobsters-agree.md new file mode 100644 index 000000000000..dae24d434073 --- /dev/null +++ b/.changeset/quiet-lobsters-agree.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: clone server data before passing it to universal load diff --git a/packages/kit/src/runtime/server/page/load_data.js b/packages/kit/src/runtime/server/page/load_data.js index 75cf68d335e8..03021eae333f 100644 --- a/packages/kit/src/runtime/server/page/load_data.js +++ b/packages/kit/src/runtime/server/page/load_data.js @@ -192,7 +192,7 @@ export async function load_data({ const result = await node.universal.load.call(null, { url: event.url, params: event.params, - data: server_data_node?.data ?? null, + data: server_data_node?.data ? Object.assign({}, server_data_node.data) : null, route: event.route, fetch: create_universal_fetch(event, state, fetched, csr, resolve_opts), setHeaders: event.setHeaders, diff --git a/packages/kit/src/runtime/server/utils.js b/packages/kit/src/runtime/server/utils.js index f211739140e1..1b3a44f372c4 100644 --- a/packages/kit/src/runtime/server/utils.js +++ b/packages/kit/src/runtime/server/utils.js @@ -6,18 +6,6 @@ import { HttpError } from '../control.js'; import { fix_stack_trace } from '../shared-server.js'; import { ENDPOINT_METHODS } from '../../constants.js'; -/** @param {any} body */ -export function is_pojo(body) { - if (typeof body !== 'object') return false; - - if (body) { - if (body instanceof Uint8Array) return false; - if (body instanceof ReadableStream) return false; - } - - return true; -} - /** * @param {Partial>} mod * @param {import('types').HttpMethod} method diff --git a/packages/kit/test/apps/basics/src/routes/load/mutated-server-data/+page.js b/packages/kit/test/apps/basics/src/routes/load/mutated-server-data/+page.js new file mode 100644 index 000000000000..372e9e6ed5c2 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/load/mutated-server-data/+page.js @@ -0,0 +1,11 @@ +class CustomClass {} + +export function load({ data }) { + // @ts-ignore we want to mutate the server load data + data.b = new CustomClass(); + // @ts-ignore we want to mutate the server load data + data.d = { + a: new CustomClass() + }; + return data; +} diff --git a/packages/kit/test/apps/basics/src/routes/load/mutated-server-data/+page.server.js b/packages/kit/test/apps/basics/src/routes/load/mutated-server-data/+page.server.js new file mode 100644 index 000000000000..367ed870f953 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/load/mutated-server-data/+page.server.js @@ -0,0 +1,6 @@ +export function load() { + return { + a: 1, + c: new Promise((resolve) => resolve()) + }; +} diff --git a/packages/kit/test/apps/basics/src/routes/load/mutated-server-data/+page.svelte b/packages/kit/test/apps/basics/src/routes/load/mutated-server-data/+page.svelte new file mode 100644 index 000000000000..48aa4cb69f99 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/load/mutated-server-data/+page.svelte @@ -0,0 +1 @@ +

hello world

diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index 3922d127039e..2ae75035150f 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -575,6 +575,11 @@ test.describe('Load', () => { expect(await page.textContent('h1')).toBe('404'); }); + + test('data is not mutated by universal load', async ({ page }) => { + await page.goto('/load/mutated-server-data'); + expect(await page.textContent('p')).toBe('hello world'); + }); }); test.describe('Nested layouts', () => {