diff --git a/documentation/docs/98-reference/.generated/shared-errors.md b/documentation/docs/98-reference/.generated/shared-errors.md
index 4c81d7b89452..6c31aaafd0df 100644
--- a/documentation/docs/98-reference/.generated/shared-errors.md
+++ b/documentation/docs/98-reference/.generated/shared-errors.md
@@ -60,6 +60,43 @@ Certain lifecycle methods can only be used during component initialisation. To f
```
+### snippet_without_render_tag
+
+```
+Attempted to render a snippet without a `{@render}` block. This would cause the snippet code to be stringified instead of its content being rendered to the DOM. To fix this, change `{snippet}` to `{@render snippet()}`.
+```
+
+A component throwing this error will look something like this (`children` is not being rendered):
+
+```svelte
+
+
+{children}
+```
+
+...or like this (a parent component is passing a snippet where a non-snippet value is expected):
+
+```svelte
+
+
+ {#snippet label()}
+ Hi!
+ {/snippet}
+
+```
+
+```svelte
+
+
+
+
+
{label}
+```
+
### store_invalid_shape
```
diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md
index c8f0ad7ed964..4ffcb263abb5 100644
--- a/packages/svelte/CHANGELOG.md
+++ b/packages/svelte/CHANGELOG.md
@@ -1,5 +1,17 @@
# svelte
+## 5.27.1
+
+### Patch Changes
+
+- chore: default params for html blocks ([#15778](https://github.com/sveltejs/svelte/pull/15778))
+
+- fix: correct suggested type for custom events without detail ([#15763](https://github.com/sveltejs/svelte/pull/15763))
+
+- fix: Throw on unrendered snippets in `dev` ([#15766](https://github.com/sveltejs/svelte/pull/15766))
+
+- fix: avoid unnecessary read version increments ([#15777](https://github.com/sveltejs/svelte/pull/15777))
+
## 5.27.0
### Minor Changes
diff --git a/packages/svelte/messages/shared-errors/errors.md b/packages/svelte/messages/shared-errors/errors.md
index 20f3d193d928..4b4d3322028d 100644
--- a/packages/svelte/messages/shared-errors/errors.md
+++ b/packages/svelte/messages/shared-errors/errors.md
@@ -52,6 +52,41 @@ Certain lifecycle methods can only be used during component initialisation. To f
```
+## snippet_without_render_tag
+
+> Attempted to render a snippet without a `{@render}` block. This would cause the snippet code to be stringified instead of its content being rendered to the DOM. To fix this, change `{snippet}` to `{@render snippet()}`.
+
+A component throwing this error will look something like this (`children` is not being rendered):
+
+```svelte
+
+
+{children}
+```
+
+...or like this (a parent component is passing a snippet where a non-snippet value is expected):
+
+```svelte
+
+
+ {#snippet label()}
+ Hi!
+ {/snippet}
+
+```
+
+```svelte
+
+
+
+
+
{label}
+```
+
## store_invalid_shape
> `%name%` is not a store with a `subscribe` method
diff --git a/packages/svelte/package.json b/packages/svelte/package.json
index af78d2679ab8..7ad4835a9a41 100644
--- a/packages/svelte/package.json
+++ b/packages/svelte/package.json
@@ -2,7 +2,7 @@
"name": "svelte",
"description": "Cybernetically enhanced web apps",
"license": "MIT",
- "version": "5.27.0",
+ "version": "5.27.1",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/HtmlTag.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/HtmlTag.js
index 32439879de38..ace73691d164 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/HtmlTag.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/HtmlTag.js
@@ -11,17 +11,22 @@ import * as b from '../../../../utils/builders.js';
export function HtmlTag(node, context) {
context.state.template.push('');
- // push into init, so that bindings run afterwards, which might trigger another run and override hydration
- context.state.init.push(
- b.stmt(
- b.call(
- '$.html',
- context.state.node,
- b.thunk(/** @type {Expression} */ (context.visit(node.expression))),
- b.literal(context.state.metadata.namespace === 'svg'),
- b.literal(context.state.metadata.namespace === 'mathml'),
- is_ignored(node, 'hydration_html_changed') && b.true
- )
+ const expression = /** @type {Expression} */ (context.visit(node.expression));
+
+ const is_svg = context.state.metadata.namespace === 'svg';
+ const is_mathml = context.state.metadata.namespace === 'mathml';
+
+ const statement = b.stmt(
+ b.call(
+ '$.html',
+ context.state.node,
+ b.thunk(expression),
+ is_svg && b.true,
+ is_mathml && b.true,
+ is_ignored(node, 'hydration_html_changed') && b.true
)
);
+
+ // push into init, so that bindings run afterwards, which might trigger another run and override hydration
+ context.state.init.push(statement);
}
diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js
index cae3e7d79c94..a67fcc888510 100644
--- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js
+++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js
@@ -1,4 +1,4 @@
-/** @import { BlockStatement } from 'estree' */
+/** @import { ArrowFunctionExpression, BlockStatement, CallExpression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */
import { dev } from '../../../../state.js';
@@ -9,20 +9,27 @@ import * as b from '../../../../utils/builders.js';
* @param {ComponentContext} context
*/
export function SnippetBlock(node, context) {
- const fn = b.function_declaration(
- node.expression,
- [b.id('$$payload'), ...node.parameters],
- /** @type {BlockStatement} */ (context.visit(node.body))
- );
+ const body = /** @type {BlockStatement} */ (context.visit(node.body));
+
if (dev) {
- fn.body.body.unshift(b.stmt(b.call('$.validate_snippet_args', b.id('$$payload'))));
+ body.body.unshift(b.stmt(b.call('$.validate_snippet_args', b.id('$$payload'))));
}
+
+ /** @type {ArrowFunctionExpression | CallExpression} */
+ let fn = b.arrow([b.id('$$payload'), ...node.parameters], body);
+
+ if (dev) {
+ fn = b.call('$.prevent_snippet_stringification', fn);
+ }
+
+ const declaration = b.declaration('const', [b.declarator(node.expression, fn)]);
+
// @ts-expect-error - TODO remove this hack once $$render_inner for legacy bindings is gone
fn.___snippet = true;
if (node.metadata.can_hoist) {
- context.state.hoisted.push(fn);
+ context.state.hoisted.push(declaration);
} else {
- context.state.init.push(fn);
+ context.state.init.push(declaration);
}
}
diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js
index 695161ff9b60..f4b3dd1b09aa 100644
--- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js
+++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/component.js
@@ -4,6 +4,7 @@
import { empty_comment, build_attribute_value } from './utils.js';
import * as b from '../../../../../utils/builders.js';
import { is_element_node } from '../../../../nodes.js';
+import { dev } from '../../../../../state.js';
/**
* @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node
@@ -238,7 +239,13 @@ export function build_inline_component(node, expression, context) {
)
) {
// create `children` prop...
- push_prop(b.prop('init', b.id('children'), slot_fn));
+ push_prop(
+ b.prop(
+ 'init',
+ b.id('children'),
+ dev ? b.call('$.prevent_snippet_stringification', slot_fn) : slot_fn
+ )
+ );
// and `$$slots.default: true` so that `` on the child works
serialized_slots.push(b.init(slot_name, b.true));
diff --git a/packages/svelte/src/index-client.js b/packages/svelte/src/index-client.js
index fd8e999da763..efd5628ae951 100644
--- a/packages/svelte/src/index-client.js
+++ b/packages/svelte/src/index-client.js
@@ -114,7 +114,7 @@ function create_custom_event(type, detail, { bubbles = false, cancelable = false
* The event dispatcher can be typed to narrow the allowed event names and the type of the `detail` argument:
* ```ts
* const dispatch = createEventDispatcher<{
- * loaded: never; // does not take a detail argument
+ * loaded: null; // does not take a detail argument
* change: string; // takes a detail argument of type string, which is required
* optional: number | null; // takes an optional detail argument of type number
* }>();
diff --git a/packages/svelte/src/internal/client/dev/debug.js b/packages/svelte/src/internal/client/dev/debug.js
new file mode 100644
index 000000000000..f449dfa2ccd1
--- /dev/null
+++ b/packages/svelte/src/internal/client/dev/debug.js
@@ -0,0 +1,109 @@
+/** @import { Derived, Effect, Value } from '#client' */
+
+import {
+ BLOCK_EFFECT,
+ BOUNDARY_EFFECT,
+ BRANCH_EFFECT,
+ CLEAN,
+ DERIVED,
+ EFFECT,
+ MAYBE_DIRTY,
+ RENDER_EFFECT,
+ ROOT_EFFECT
+} from '../constants.js';
+
+/**
+ *
+ * @param {Effect} effect
+ */
+export function root(effect) {
+ while (effect.parent !== null) {
+ effect = effect.parent;
+ }
+
+ return effect;
+}
+
+/**
+ *
+ * @param {Effect} effect
+ */
+export function log_effect_tree(effect, depth = 0) {
+ const flags = effect.f;
+
+ let label = '(unknown)';
+
+ if ((flags & ROOT_EFFECT) !== 0) {
+ label = 'root';
+ } else if ((flags & BOUNDARY_EFFECT) !== 0) {
+ label = 'boundary';
+ } else if ((flags & BLOCK_EFFECT) !== 0) {
+ label = 'block';
+ } else if ((flags & BRANCH_EFFECT) !== 0) {
+ label = 'branch';
+ } else if ((flags & RENDER_EFFECT) !== 0) {
+ label = 'render effect';
+ } else if ((flags & EFFECT) !== 0) {
+ label = 'effect';
+ }
+
+ let status =
+ (flags & CLEAN) !== 0 ? 'clean' : (flags & MAYBE_DIRTY) !== 0 ? 'maybe dirty' : 'dirty';
+
+ // eslint-disable-next-line no-console
+ console.group(`%c${label} (${status})`, `font-weight: ${status === 'clean' ? 'normal' : 'bold'}`);
+
+ if (depth === 0) {
+ const callsite = new Error().stack
+ ?.split('\n')[2]
+ .replace(/\s+at (?: \w+\(?)?(.+)\)?/, (m, $1) => $1.replace(/\?[^:]+/, ''));
+
+ // eslint-disable-next-line no-console
+ console.log(callsite);
+ }
+
+ if (effect.deps !== null) {
+ // eslint-disable-next-line no-console
+ console.groupCollapsed('%cdeps', 'font-weight: normal');
+
+ for (const dep of effect.deps) {
+ log_dep(dep);
+ }
+
+ // eslint-disable-next-line no-console
+ console.groupEnd();
+ }
+
+ let child = effect.first;
+ while (child !== null) {
+ log_effect_tree(child, depth + 1);
+ child = child.next;
+ }
+
+ // eslint-disable-next-line no-console
+ console.groupEnd();
+}
+
+/**
+ *
+ * @param {Value} dep
+ */
+function log_dep(dep) {
+ if ((dep.f & DERIVED) !== 0) {
+ const derived = /** @type {Derived} */ (dep);
+
+ // eslint-disable-next-line no-console
+ console.groupCollapsed('%cderived', 'font-weight: normal', derived.v);
+ if (derived.deps) {
+ for (const d of derived.deps) {
+ log_dep(d);
+ }
+ }
+
+ // eslint-disable-next-line no-console
+ console.groupEnd();
+ } else {
+ // eslint-disable-next-line no-console
+ console.log('state', dep.v);
+ }
+}
diff --git a/packages/svelte/src/internal/client/dom/blocks/html.js b/packages/svelte/src/internal/client/dom/blocks/html.js
index b3fc5a9c725d..92c824347894 100644
--- a/packages/svelte/src/internal/client/dom/blocks/html.js
+++ b/packages/svelte/src/internal/client/dom/blocks/html.js
@@ -1,6 +1,6 @@
/** @import { Effect, TemplateNode } from '#client' */
import { FILENAME, HYDRATION_ERROR } from '../../../../constants.js';
-import { block, branch, destroy_effect } from '../../reactivity/effects.js';
+import { remove_effect_dom, template_effect } from '../../reactivity/effects.js';
import { hydrate_next, hydrate_node, hydrating, set_hydrate_node } from '../hydration.js';
import { create_fragment_from_html } from '../reconciler.js';
import { assign_nodes } from '../template.js';
@@ -9,6 +9,7 @@ import { hash, sanitize_location } from '../../../../utils.js';
import { DEV } from 'esm-env';
import { dev_current_component_function } from '../../context.js';
import { get_first_child, get_next_sibling } from '../operations.js';
+import { active_effect } from '../../runtime.js';
/**
* @param {Element} element
@@ -34,89 +35,81 @@ function check_hash(element, server_hash, value) {
/**
* @param {Element | Text | Comment} node
* @param {() => string} get_value
- * @param {boolean} svg
- * @param {boolean} mathml
+ * @param {boolean} [svg]
+ * @param {boolean} [mathml]
* @param {boolean} [skip_warning]
* @returns {void}
*/
-export function html(node, get_value, svg, mathml, skip_warning) {
+export function html(node, get_value, svg = false, mathml = false, skip_warning = false) {
var anchor = node;
var value = '';
- /** @type {Effect | undefined} */
- var effect;
+ template_effect(() => {
+ var effect = /** @type {Effect} */ (active_effect);
- block(() => {
if (value === (value = get_value() ?? '')) {
- if (hydrating) {
- hydrate_next();
- }
+ if (hydrating) hydrate_next();
return;
}
- if (effect !== undefined) {
- destroy_effect(effect);
- effect = undefined;
+ if (effect.nodes_start !== null) {
+ remove_effect_dom(effect.nodes_start, /** @type {TemplateNode} */ (effect.nodes_end));
+ effect.nodes_start = effect.nodes_end = null;
}
if (value === '') return;
- effect = branch(() => {
- if (hydrating) {
- // We're deliberately not trying to repair mismatches between server and client,
- // as it's costly and error-prone (and it's an edge case to have a mismatch anyway)
- var hash = /** @type {Comment} */ (hydrate_node).data;
- var next = hydrate_next();
- var last = next;
-
- while (
- next !== null &&
- (next.nodeType !== 8 || /** @type {Comment} */ (next).data !== '')
- ) {
- last = next;
- next = /** @type {TemplateNode} */ (get_next_sibling(next));
- }
-
- if (next === null) {
- w.hydration_mismatch();
- throw HYDRATION_ERROR;
- }
-
- if (DEV && !skip_warning) {
- check_hash(/** @type {Element} */ (next.parentNode), hash, value);
- }
-
- assign_nodes(hydrate_node, last);
- anchor = set_hydrate_node(next);
- return;
- }
+ if (hydrating) {
+ // We're deliberately not trying to repair mismatches between server and client,
+ // as it's costly and error-prone (and it's an edge case to have a mismatch anyway)
+ var hash = /** @type {Comment} */ (hydrate_node).data;
+ var next = hydrate_next();
+ var last = next;
- var html = value + '';
- if (svg) html = ``;
- else if (mathml) html = ``;
+ while (next !== null && (next.nodeType !== 8 || /** @type {Comment} */ (next).data !== '')) {
+ last = next;
+ next = /** @type {TemplateNode} */ (get_next_sibling(next));
+ }
- // Don't use create_fragment_with_script_from_html here because that would mean script tags are executed.
- // @html is basically `.innerHTML = ...` and that doesn't execute scripts either due to security reasons.
- /** @type {DocumentFragment | Element} */
- var node = create_fragment_from_html(html);
+ if (next === null) {
+ w.hydration_mismatch();
+ throw HYDRATION_ERROR;
+ }
- if (svg || mathml) {
- node = /** @type {Element} */ (get_first_child(node));
+ if (DEV && !skip_warning) {
+ check_hash(/** @type {Element} */ (next.parentNode), hash, value);
}
- assign_nodes(
- /** @type {TemplateNode} */ (get_first_child(node)),
- /** @type {TemplateNode} */ (node.lastChild)
- );
-
- if (svg || mathml) {
- while (get_first_child(node)) {
- anchor.before(/** @type {Node} */ (get_first_child(node)));
- }
- } else {
- anchor.before(node);
+ assign_nodes(hydrate_node, last);
+ anchor = set_hydrate_node(next);
+ return;
+ }
+
+ var html = value + '';
+ if (svg) html = ``;
+ else if (mathml) html = ``;
+
+ // Don't use create_fragment_with_script_from_html here because that would mean script tags are executed.
+ // @html is basically `.innerHTML = ...` and that doesn't execute scripts either due to security reasons.
+ /** @type {DocumentFragment | Element} */
+ var node = create_fragment_from_html(html);
+
+ if (svg || mathml) {
+ node = /** @type {Element} */ (get_first_child(node));
+ }
+
+ assign_nodes(
+ /** @type {TemplateNode} */ (get_first_child(node)),
+ /** @type {TemplateNode} */ (node.lastChild)
+ );
+
+ if (svg || mathml) {
+ while (get_first_child(node)) {
+ anchor.before(/** @type {Node} */ (get_first_child(node)));
}
- });
+ } else {
+ anchor.before(node);
+ }
});
}
diff --git a/packages/svelte/src/internal/client/dom/blocks/snippet.js b/packages/svelte/src/internal/client/dom/blocks/snippet.js
index b916a02ce55f..a48153900fde 100644
--- a/packages/svelte/src/internal/client/dom/blocks/snippet.js
+++ b/packages/svelte/src/internal/client/dom/blocks/snippet.js
@@ -15,6 +15,7 @@ import * as e from '../../errors.js';
import { DEV } from 'esm-env';
import { get_first_child, get_next_sibling } from '../operations.js';
import { noop } from '../../../shared/utils.js';
+import { prevent_snippet_stringification } from '../../../shared/validate.js';
/**
* @template {(node: TemplateNode, ...args: any[]) => void} SnippetFn
@@ -60,7 +61,7 @@ export function snippet(node, get_snippet, ...args) {
* @param {(node: TemplateNode, ...args: any[]) => void} fn
*/
export function wrap_snippet(component, fn) {
- return (/** @type {TemplateNode} */ node, /** @type {any[]} */ ...args) => {
+ const snippet = (/** @type {TemplateNode} */ node, /** @type {any[]} */ ...args) => {
var previous_component_function = dev_current_component_function;
set_dev_current_component_function(component);
@@ -70,6 +71,10 @@ export function wrap_snippet(component, fn) {
set_dev_current_component_function(previous_component_function);
}
};
+
+ prevent_snippet_stringification(snippet);
+
+ return snippet;
}
/**
diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js
index e977bf3b0fe9..14d6e29f5bb4 100644
--- a/packages/svelte/src/internal/client/index.js
+++ b/packages/svelte/src/internal/client/index.js
@@ -157,7 +157,8 @@ export {
invalid_default_snippet,
validate_dynamic_element_tag,
validate_store,
- validate_void_dynamic_element
+ validate_void_dynamic_element,
+ prevent_snippet_stringification
} from '../shared/validate.js';
export { strict_equals, equals } from './dev/equality.js';
export { log_if_contains_state } from './dev/console-log.js';
diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js
index 468bb94ab428..76b014c916c6 100644
--- a/packages/svelte/src/internal/client/reactivity/effects.js
+++ b/packages/svelte/src/internal/client/reactivity/effects.js
@@ -427,18 +427,7 @@ export function destroy_effect(effect, remove_dom = true) {
var removed = false;
if ((remove_dom || (effect.f & HEAD_EFFECT) !== 0) && effect.nodes_start !== null) {
- /** @type {TemplateNode | null} */
- var node = effect.nodes_start;
- var end = effect.nodes_end;
-
- while (node !== null) {
- /** @type {TemplateNode | null} */
- var next = node === end ? null : /** @type {TemplateNode} */ (get_next_sibling(node));
-
- node.remove();
- node = next;
- }
-
+ remove_effect_dom(effect.nodes_start, /** @type {TemplateNode} */ (effect.nodes_end));
removed = true;
}
@@ -480,6 +469,21 @@ export function destroy_effect(effect, remove_dom = true) {
null;
}
+/**
+ *
+ * @param {TemplateNode | null} node
+ * @param {TemplateNode} end
+ */
+export function remove_effect_dom(node, end) {
+ while (node !== null) {
+ /** @type {TemplateNode | null} */
+ var next = node === end ? null : /** @type {TemplateNode} */ (get_next_sibling(node));
+
+ node.remove();
+ node = next;
+ }
+}
+
/**
* Detach an effect from the effect tree, freeing up memory and
* reducing the amount of work that happens on subsequent traversals
diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js
index 2acad3d2580d..e621536055b5 100644
--- a/packages/svelte/src/internal/client/runtime.js
+++ b/packages/svelte/src/internal/client/runtime.js
@@ -469,7 +469,7 @@ export function update_reaction(reaction) {
// we need to increment the read version to ensure that
// any dependencies in this reaction aren't marked with
// the same version
- if (previous_reaction !== reaction) {
+ if (previous_reaction !== null && previous_reaction !== reaction) {
read_version++;
if (untracked_writes !== null) {
diff --git a/packages/svelte/src/internal/server/index.js b/packages/svelte/src/internal/server/index.js
index d711778a44ea..b58a1d4372a6 100644
--- a/packages/svelte/src/internal/server/index.js
+++ b/packages/svelte/src/internal/server/index.js
@@ -509,7 +509,8 @@ export { fallback } from '../shared/utils.js';
export {
invalid_default_snippet,
validate_dynamic_element_tag,
- validate_void_dynamic_element
+ validate_void_dynamic_element,
+ prevent_snippet_stringification
} from '../shared/validate.js';
export { escape_html as escape };
diff --git a/packages/svelte/src/internal/shared/errors.js b/packages/svelte/src/internal/shared/errors.js
index 2e89dc1ad109..b8606fbf6f7d 100644
--- a/packages/svelte/src/internal/shared/errors.js
+++ b/packages/svelte/src/internal/shared/errors.js
@@ -48,6 +48,21 @@ export function lifecycle_outside_component(name) {
}
}
+/**
+ * Attempted to render a snippet without a `{@render}` block. This would cause the snippet code to be stringified instead of its content being rendered to the DOM. To fix this, change `{snippet}` to `{@render snippet()}`.
+ * @returns {never}
+ */
+export function snippet_without_render_tag() {
+ if (DEV) {
+ const error = new Error(`snippet_without_render_tag\nAttempted to render a snippet without a \`{@render}\` block. This would cause the snippet code to be stringified instead of its content being rendered to the DOM. To fix this, change \`{snippet}\` to \`{@render snippet()}\`.\nhttps://svelte.dev/e/snippet_without_render_tag`);
+
+ error.name = 'Svelte error';
+ throw error;
+ } else {
+ throw new Error(`https://svelte.dev/e/snippet_without_render_tag`);
+ }
+}
+
/**
* `%name%` is not a store with a `subscribe` method
* @param {string} name
diff --git a/packages/svelte/src/internal/shared/validate.js b/packages/svelte/src/internal/shared/validate.js
index 852c0e83bfb1..bbb237594bec 100644
--- a/packages/svelte/src/internal/shared/validate.js
+++ b/packages/svelte/src/internal/shared/validate.js
@@ -35,3 +35,15 @@ export function validate_store(store, name) {
e.store_invalid_shape(name);
}
}
+
+/**
+ * @template {() => unknown} T
+ * @param {T} fn
+ */
+export function prevent_snippet_stringification(fn) {
+ fn.toString = () => {
+ e.snippet_without_render_tag();
+ return '';
+ };
+ return fn;
+}
diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js
index 27a39136f8c2..b0424e82325a 100644
--- a/packages/svelte/src/version.js
+++ b/packages/svelte/src/version.js
@@ -4,5 +4,5 @@
* The current version, as set in package.json.
* @type {string}
*/
-export const VERSION = '5.27.0';
+export const VERSION = '5.27.1';
export const PUBLIC_VERSION = '5';
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-dev/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-dev/_config.js
new file mode 100644
index 000000000000..94c5de10af60
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-dev/_config.js
@@ -0,0 +1,8 @@
+import { test } from '../../test';
+
+export default test({
+ compileOptions: {
+ dev: true
+ },
+ runtime_error: 'snippet_without_render_tag'
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-dev/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-dev/main.svelte
new file mode 100644
index 000000000000..3f8edfe4fafc
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-dev/main.svelte
@@ -0,0 +1,5 @@
+{testSnippet}
+
+{#snippet testSnippet()}
+
hi again
+{/snippet}
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/_config.js
new file mode 100644
index 000000000000..f47bee71df87
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/_config.js
@@ -0,0 +1,3 @@
+import { test } from '../../test';
+
+export default test({});
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/main.svelte
new file mode 100644
index 000000000000..3f8edfe4fafc
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-block-without-render-tag-prod/main.svelte
@@ -0,0 +1,5 @@
+{testSnippet}
+
+{#snippet testSnippet()}
+
hi again
+{/snippet}
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/_config.js
new file mode 100644
index 000000000000..f47bee71df87
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/_config.js
@@ -0,0 +1,3 @@
+import { test } from '../../test';
+
+export default test({});
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/main.svelte
new file mode 100644
index 000000000000..4a4ed3176f24
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/main.svelte
@@ -0,0 +1,5 @@
+
+
+Hi
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/unrendered-children.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/unrendered-children.svelte
new file mode 100644
index 000000000000..6b7154a5a406
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev-prod/unrendered-children.svelte
@@ -0,0 +1,5 @@
+
+
+{children}
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev/_config.js
new file mode 100644
index 000000000000..94c5de10af60
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev/_config.js
@@ -0,0 +1,8 @@
+import { test } from '../../test';
+
+export default test({
+ compileOptions: {
+ dev: true
+ },
+ runtime_error: 'snippet_without_render_tag'
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev/main.svelte
new file mode 100644
index 000000000000..4a4ed3176f24
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev/main.svelte
@@ -0,0 +1,5 @@
+
+
+Hi
diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev/unrendered-children.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev/unrendered-children.svelte
new file mode 100644
index 000000000000..6b7154a5a406
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/snippet-children-without-render-tag-dev/unrendered-children.svelte
@@ -0,0 +1,5 @@
+
+
+{children}
diff --git a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js
index cadae2cf15c0..04bfbf6ae47b 100644
--- a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js
+++ b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js
@@ -1,9 +1,9 @@
import * as $ from 'svelte/internal/server';
import TextInput from './Child.svelte';
-function snippet($$payload) {
+const snippet = ($$payload) => {
$$payload.out += `Something`;
-}
+};
export default function Bind_component_snippet($$payload) {
let value = '';
diff --git a/packages/svelte/tests/snapshot/samples/skip-static-subtree/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/skip-static-subtree/_expected/client/index.svelte.js
index b341d39f28fb..541b56a407ba 100644
--- a/packages/svelte/tests/snapshot/samples/skip-static-subtree/_expected/client/index.svelte.js
+++ b/packages/svelte/tests/snapshot/samples/skip-static-subtree/_expected/client/index.svelte.js
@@ -13,7 +13,7 @@ export default function Skip_static_subtree($$anchor, $$props) {
var node = $.sibling(h1, 10);
- $.html(node, () => $$props.content, false, false);
+ $.html(node, () => $$props.content);
$.next(14);
$.reset(main);
diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts
index 6f12daf18778..8fc174b0a944 100644
--- a/packages/svelte/types/index.d.ts
+++ b/packages/svelte/types/index.d.ts
@@ -381,7 +381,7 @@ declare module 'svelte' {
* The event dispatcher can be typed to narrow the allowed event names and the type of the `detail` argument:
* ```ts
* const dispatch = createEventDispatcher<{
- * loaded: never; // does not take a detail argument
+ * loaded: null; // does not take a detail argument
* change: string; // takes a detail argument of type string, which is required
* optional: number | null; // takes an optional detail argument of type number
* }>();
pFad - Phonifier reborn
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.