diff --git a/.changeset/itchy-panthers-shave.md b/.changeset/itchy-panthers-shave.md new file mode 100644 index 0000000000..c47ab1f61c --- /dev/null +++ b/.changeset/itchy-panthers-shave.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: disallow mounting a snippet diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index c0d449f35b..bafaadf2b8 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -21,6 +21,7 @@ import { handle_event_propagation } from './dom/elements/events.js'; import { reset_head_anchor } from './dom/blocks/svelte-head.js'; import * as w from './warnings.js'; import * as e from './errors.js'; +import { validate_component } from '../shared/validate.js'; /** @type {Set} */ export const all_registered_events = new Set(); @@ -102,6 +103,10 @@ export function stringify(value) { * @returns {Exports} */ export function mount(component, options) { + if (DEV) { + validate_component(component); + } + const anchor = options.anchor ?? options.target.appendChild(empty()); // Don't flush previous effects to ensure order of outer effects stays consistent return flush_sync(() => _mount(component, { ...options, anchor }), false); @@ -125,6 +130,10 @@ export function mount(component, options) { * @returns {Exports} */ export function hydrate(component, options) { + if (DEV) { + validate_component(component); + } + const target = options.target; const previous_hydrate_nodes = hydrate_nodes; diff --git a/packages/svelte/tests/runtime-runes/samples/mount-snippet-error/_config.js b/packages/svelte/tests/runtime-runes/samples/mount-snippet-error/_config.js new file mode 100644 index 0000000000..3ba2b358ea --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/mount-snippet-error/_config.js @@ -0,0 +1,12 @@ +import { test } from '../../test'; + +export default test({ + compileOptions: { + dev: true + }, + async test({ assert, target }) { + const div = target.querySelector('div'); + assert.htmlEqual(div?.innerHTML || '', ''); + }, + runtime_error: 'snippet_used_as_component\nA snippet must be rendered with `{@render ...}`' +}); diff --git a/packages/svelte/tests/runtime-runes/samples/mount-snippet-error/main.svelte b/packages/svelte/tests/runtime-runes/samples/mount-snippet-error/main.svelte new file mode 100644 index 0000000000..075fbba24e --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/mount-snippet-error/main.svelte @@ -0,0 +1,14 @@ + + +
+{#snippet foo()} + shouldnt be rendered +{/snippet} \ No newline at end of file