diff --git a/.changeset/chilled-fireants-learn.md b/.changeset/chilled-fireants-learn.md new file mode 100644 index 000000000000..3796f57910ba --- /dev/null +++ b/.changeset/chilled-fireants-learn.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': major +--- + +breaking: remove deprecated `use:enhance` callback values diff --git a/.changeset/mean-moose-smell.md b/.changeset/mean-moose-smell.md new file mode 100644 index 000000000000..17d98b2cdbae --- /dev/null +++ b/.changeset/mean-moose-smell.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': major +--- + +breaking: error if form without multipart/form-data enctype contains a file input diff --git a/documentation/docs/60-appendix/30-migrating-to-sveltekit-2.md b/documentation/docs/60-appendix/30-migrating-to-sveltekit-2.md index 6cda9848e788..0f8babf08977 100644 --- a/documentation/docs/60-appendix/30-migrating-to-sveltekit-2.md +++ b/documentation/docs/60-appendix/30-migrating-to-sveltekit-2.md @@ -105,6 +105,16 @@ As such, SvelteKit 2 replaces `resolvePath` with a (slightly better named) funct `svelte-migrate` will do the method replacement for you, though if you later prepend the result with `base`, you need to remove that yourself. +## `form` and `data` have been removed from `use:enhance` callbacks + +If you provide a callback to [`use:enhance`](/docs/form-actions#progressive-enhancement-use-enhance), it will be called with an object containing various useful properties. + +In SvelteKit 1, those properties included `form` and `data`. These were deprecated some time ago in favour of `formElement` and `formData`, and have been removed altogether in SvelteKit 2. + +## Forms containing file inputs must use `multipart/form-data` + +If a form contains an `` but does not have an `enctype="multipart/form-data"` attribute, non-JS submissions will omit the file. SvelteKit 2 will throw an error if it encounters a form like this during a `use:enhance` submission to ensure that your forms work correctly when JavaScript is not present. + ## Updated dependency requirements SvelteKit requires Node `18.13` or higher, Vite `^5.0`, vite-plugin-svelte `^3.0`, TypeScript `^5.0` and Svelte version 4 or higher. `svelte-migrate` will do the `package.json` bumps for you. diff --git a/packages/kit/src/exports/public.d.ts b/packages/kit/src/exports/public.d.ts index 0292c8cb285c..f60171d86015 100644 --- a/packages/kit/src/exports/public.d.ts +++ b/packages/kit/src/exports/public.d.ts @@ -1247,17 +1247,7 @@ export type SubmitFunction< Failure extends Record | undefined = Record > = (input: { action: URL; - /** - * use `formData` instead of `data` - * @deprecated - */ - data: FormData; formData: FormData; - /** - * use `formElement` instead of `form` - * @deprecated - */ - form: HTMLFormElement; formElement: HTMLFormElement; controller: AbortController; submitter: HTMLElement | null; @@ -1265,17 +1255,7 @@ export type SubmitFunction< }) => MaybePromise< | void | ((opts: { - /** - * use `formData` instead of `data` - * @deprecated - */ - data: FormData; formData: FormData; - /** - * use `formElement` instead of `form` - * @deprecated - */ - form: HTMLFormElement; formElement: HTMLFormElement; action: URL; result: ActionResult; diff --git a/packages/kit/src/runtime/app/forms.js b/packages/kit/src/runtime/app/forms.js index d1f6d70323e4..bd2a81fc8656 100644 --- a/packages/kit/src/runtime/app/forms.js +++ b/packages/kit/src/runtime/app/forms.js @@ -49,20 +49,6 @@ export function deserialize(result) { return parsed; } -/** - * @param {string} old_name - * @param {string} new_name - * @param {string} call_location - * @returns void - */ -function warn_on_access(old_name, new_name, call_location) { - if (!DEV) return; - // TODO 2.0: Remove this code - console.warn( - `\`${old_name}\` has been deprecated in favor of \`${new_name}\`. \`${old_name}\` will be removed in a future version. (Called from ${call_location})` - ); -} - /** * Shallow clone an element, so that we can access e.g. `form.action` without worrying * that someone has added an `` (https://github.com/sveltejs/kit/issues/7593) @@ -157,11 +143,9 @@ export function enhance(form_element, submit = () => {}) { if (DEV && clone(form_element).enctype !== 'multipart/form-data') { for (const value of form_data.values()) { if (value instanceof File) { - // TODO 2.0: Upgrade to `throw Error` - console.warn( - 'Your form contains fields, but is missing the `enctype="multipart/form-data"` attribute. This will lead to inconsistent behavior between enhanced and native forms. For more details, see https://github.com/sveltejs/kit/issues/9819. This will be upgraded to an error in v2.0.' + throw new Error( + 'Your form contains fields, but is missing the necessary `enctype="multipart/form-data"` attribute. This will lead to inconsistent behavior between enhanced and native forms. For more details, see https://github.com/sveltejs/kit/issues/9819.' ); - break; } } } @@ -176,21 +160,12 @@ export function enhance(form_element, submit = () => {}) { let cancelled = false; const cancel = () => (cancelled = true); - // TODO 2.0: Remove `data` and `form` const callback = (await submit({ action, cancel, controller, - get data() { - warn_on_access('data', 'formData', 'use:enhance submit function'); - return form_data; - }, formData: form_data, - get form() { - warn_on_access('form', 'formElement', 'use:enhance submit function'); - return form_element; - }, formElement: form_element, submitter: event.submitter })) ?? fallback_callback; @@ -220,15 +195,7 @@ export function enhance(form_element, submit = () => {}) { callback({ action, - get data() { - warn_on_access('data', 'formData', 'callback returned from use:enhance submit function'); - return form_data; - }, formData: form_data, - get form() { - warn_on_access('form', 'formElement', 'callback returned from use:enhance submit function'); - return form_element; - }, formElement: form_element, update: (opts) => fallback_callback({ diff --git a/packages/kit/test/apps/basics/src/routes/actions/enhance/old-property-access/+page.server.js b/packages/kit/test/apps/basics/src/routes/actions/enhance/old-property-access/+page.server.js deleted file mode 100644 index 4bdf1c67412b..000000000000 --- a/packages/kit/test/apps/basics/src/routes/actions/enhance/old-property-access/+page.server.js +++ /dev/null @@ -1,26 +0,0 @@ -// TODO 2.0: Remove this code and corresponding tests -export const actions = { - form_submit: () => { - return { - form_submit: true - }; - }, - - form_callback: () => { - return { - form_callback: true - }; - }, - - data_submit: () => { - return { - data_submit: true - }; - }, - - data_callback: () => { - return { - data_callback: true - }; - } -}; diff --git a/packages/kit/test/apps/basics/src/routes/actions/enhance/old-property-access/+page.svelte b/packages/kit/test/apps/basics/src/routes/actions/enhance/old-property-access/+page.svelte deleted file mode 100644 index 1768c5d9dc7b..000000000000 --- a/packages/kit/test/apps/basics/src/routes/actions/enhance/old-property-access/+page.svelte +++ /dev/null @@ -1,60 +0,0 @@ - - -
- -
- -
- -
- -
- -
- -
- -
diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index cb6b4954e045..27b103347672 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -918,69 +918,21 @@ test.describe('Actions', () => { expect(preSubmitContent).not.toBe(postSubmitContent); }); - test('Submitting a form with a file input but no enctype="multipart/form-data" logs a warning', async ({ + test('Submitting a form with a file input but no enctype="multipart/form-data" throws an error', async ({ page, javaScriptEnabled }) => { test.skip(!javaScriptEnabled, 'Skip when JavaScript is disabled'); test.skip(!process.env.DEV, 'Skip when not in dev mode'); await page.goto('/actions/file-without-enctype'); - const log_promise = page.waitForEvent('console'); + const error_promise = page.waitForEvent('pageerror'); await page.click('button'); - const log = await log_promise; - expect(log.text()).toBe( - 'Your form contains fields, but is missing the `enctype="multipart/form-data"` attribute. This will lead to inconsistent behavior between enhanced and native forms. For more details, see https://github.com/sveltejs/kit/issues/9819. This will be upgraded to an error in v2.0.' + const error = await error_promise; + expect(error.message).toBe( + 'Your form contains fields, but is missing the necessary `enctype="multipart/form-data"` attribute. This will lead to inconsistent behavior between enhanced and native forms. For more details, see https://github.com/sveltejs/kit/issues/9819.' ); }); - test('Accessing v2 deprecated properties results in a warning log', async ({ - page, - javaScriptEnabled - }) => { - test.skip(!javaScriptEnabled, 'skip when js is disabled'); - test.skip(!process.env.DEV, 'skip when not in dev mode'); - await page.goto('/actions/enhance/old-property-access'); - - for (const { id, old_name, new_name, call_location } of [ - { - id: 'access-form-in-submit', - old_name: 'form', - new_name: 'formElement', - call_location: 'use:enhance submit function' - }, - { - id: 'access-form-in-callback', - old_name: 'form', - new_name: 'formElement', - call_location: 'callback returned from use:enhance submit function' - }, - { - id: 'access-data-in-submit', - old_name: 'data', - new_name: 'formData', - call_location: 'use:enhance submit function' - }, - { - id: 'access-data-in-callback', - old_name: 'data', - new_name: 'formData', - call_location: 'callback returned from use:enhance submit function' - } - ]) { - await test.step(id, async () => { - const log_promise = page.waitForEvent('console'); - const button = page.locator(`#${id}`); - await button.click(); - await expect(button).toHaveAttribute('data-processed', 'true'); - const log = await log_promise; - expect(log.text()).toBe( - `\`${old_name}\` has been deprecated in favor of \`${new_name}\`. \`${old_name}\` will be removed in a future version. (Called from ${call_location})` - ); - expect(log.type()).toBe('warning'); - }); - } - }); - test('Error props are returned', async ({ page, javaScriptEnabled }) => { await page.goto('/actions/form-errors'); await page.click('button'); diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index 906332e3b809..3210343dd793 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -1229,17 +1229,7 @@ declare module '@sveltejs/kit' { Failure extends Record | undefined = Record > = (input: { action: URL; - /** - * use `formData` instead of `data` - * @deprecated - */ - data: FormData; formData: FormData; - /** - * use `formElement` instead of `form` - * @deprecated - */ - form: HTMLFormElement; formElement: HTMLFormElement; controller: AbortController; submitter: HTMLElement | null; @@ -1247,17 +1237,7 @@ declare module '@sveltejs/kit' { }) => MaybePromise< | void | ((opts: { - /** - * use `formData` instead of `data` - * @deprecated - */ - data: FormData; formData: FormData; - /** - * use `formElement` instead of `form` - * @deprecated - */ - form: HTMLFormElement; formElement: HTMLFormElement; action: URL; result: ActionResult;