diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/AwaitExpression.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/AwaitExpression.js index 90186235708a..2464f7157dbf 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/AwaitExpression.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/AwaitExpression.js @@ -53,10 +53,6 @@ export function AwaitExpression(node, context) { * @param {boolean} in_derived */ export function is_reactive_expression(path, in_derived) { - if (in_derived) { - return true; - } - let i = path.length; while (i--) { @@ -67,6 +63,27 @@ export function is_reactive_expression(path, in_derived) { parent.type === 'FunctionExpression' || parent.type === 'FunctionDeclaration' ) { + // Check if there's a reactive rune call (like $derived) between this function and the await + for (let j = i + 1; j < path.length; j++) { + const node = path[j]; + // @ts-expect-error + if (node.metadata) { + // There's a reactive expression between the function and the await + return true; + } + // Also check for $derived, $effect, etc. calls + if ( + node.type === 'CallExpression' && + node.callee?.type === 'Identifier' && + (node.callee.name === '$derived' || + node.callee.name === '$effect' || + node.callee.name === '$inspect') + ) { + // This is a reactive rune call + return true; + } + } + // No reactive expression found between function and await return false; } @@ -76,7 +93,7 @@ export function is_reactive_expression(path, in_derived) { } } - return false; + return in_derived; } /** diff --git a/packages/svelte/tests/runtime-runes/samples/const-async-function-await/_config.js b/packages/svelte/tests/runtime-runes/samples/const-async-function-await/_config.js new file mode 100644 index 000000000000..7acb1291d9b0 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/const-async-function-await/_config.js @@ -0,0 +1,31 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: `

Tab 1

`, + + async test({ assert, target }) { + const [btn1, btn2, btn3] = target.querySelectorAll('button'); + + btn2.click(); + flushSync(); + assert.htmlEqual( + target.innerHTML, + `

Tab 2

` + ); + + btn3.click(); + flushSync(); + assert.htmlEqual( + target.innerHTML, + `

Tab 3

` + ); + + btn1.click(); + flushSync(); + assert.htmlEqual( + target.innerHTML, + `

Tab 1

` + ); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/const-async-function-await/main.svelte b/packages/svelte/tests/runtime-runes/samples/const-async-function-await/main.svelte new file mode 100644 index 000000000000..279932e82823 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/const-async-function-await/main.svelte @@ -0,0 +1,37 @@ + + + + +{#if activeTab == 'tab1'} +

Tab 1

+{:else if activeTab == 'tab2'} +

Tab 2

+{:else if activeTab == 'tab3'} +

Tab 3

+{/if}