diff --git a/.changeset/odd-jobs-taste.md b/.changeset/odd-jobs-taste.md
new file mode 100644
index 0000000000..5e2b097815
--- /dev/null
+++ b/.changeset/odd-jobs-taste.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: wrap props in deriveds more conservatively in legacy mode
diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js
index 5a0adfc40c..a62666e180 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/index.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/index.js
@@ -1263,8 +1263,9 @@ const common_visitors = {
},
CallExpression(node, context) {
if (
- context.state.expression?.type === 'ExpressionTag' ||
- (context.state.expression?.type === 'SpreadAttribute' && !is_known_safe_call(node, context))
+ (context.state.expression?.type === 'ExpressionTag' ||
+ context.state.expression?.type === 'SpreadAttribute') &&
+ !is_known_safe_call(node, context)
) {
context.state.expression.metadata.contains_call_expression = true;
}
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js
index 082a6c4dee..ad36e02ddb 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js
@@ -719,11 +719,10 @@ function serialize_inline_component(node, component_name, context) {
const should_wrap_in_derived =
Array.isArray(attribute.value) &&
attribute.value.some((n) => {
- return (
- n.type === 'ExpressionTag' &&
- n.expression.type !== 'Identifier' &&
- n.expression.type !== 'MemberExpression'
- );
+ if (n.type !== 'ExpressionTag') return false;
+ return context.state.analysis.runes
+ ? n.metadata.contains_call_expression
+ : n.expression.type !== 'Identifier';
});
if (should_wrap_in_derived) {
diff --git a/packages/svelte/tests/runtime-legacy/samples/component-prop-derived/Child.svelte b/packages/svelte/tests/runtime-legacy/samples/component-prop-derived/Child.svelte
new file mode 100644
index 0000000000..3b4b540cc9
--- /dev/null
+++ b/packages/svelte/tests/runtime-legacy/samples/component-prop-derived/Child.svelte
@@ -0,0 +1,7 @@
+
+
+
diff --git a/packages/svelte/tests/runtime-legacy/samples/component-prop-derived/_config.js b/packages/svelte/tests/runtime-legacy/samples/component-prop-derived/_config.js
new file mode 100644
index 0000000000..b1bb9e5d3c
--- /dev/null
+++ b/packages/svelte/tests/runtime-legacy/samples/component-prop-derived/_config.js
@@ -0,0 +1,13 @@
+import { flushSync } from 'svelte';
+import { test } from '../../test';
+
+export default test({
+ test({ assert, logs, target }) {
+ assert.deepEqual(logs, ['x', 42]);
+
+ const btn = target.querySelector('button');
+ flushSync(() => btn?.click());
+
+ assert.deepEqual(logs, ['x', 42]);
+ }
+});
diff --git a/packages/svelte/tests/runtime-legacy/samples/component-prop-derived/main.svelte b/packages/svelte/tests/runtime-legacy/samples/component-prop-derived/main.svelte
new file mode 100644
index 0000000000..5845557173
--- /dev/null
+++ b/packages/svelte/tests/runtime-legacy/samples/component-prop-derived/main.svelte
@@ -0,0 +1,9 @@
+
+
+
+
+