diff --git a/.changeset/mighty-balloons-rush.md b/.changeset/mighty-balloons-rush.md new file mode 100644 index 000000000000..ce8c09ca55a3 --- /dev/null +++ b/.changeset/mighty-balloons-rush.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: allow async destructured deriveds diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js index 19a7de57159d..0998dc4778ea 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js @@ -171,11 +171,14 @@ export function VariableDeclaration(node, context) { context.state.transform[id.name] = { read: get_value }; const expression = /** @type {Expression} */ (context.visit(b.thunk(value))); - const call = b.call('$.derived', expression); - return b.declarator( - id, - dev ? b.call('$.tag', call, b.literal('[$state iterable]')) : call - ); + let call = b.call('$.derived', expression); + + if (dev) { + const label = `[$state ${declarator.id.type === 'ArrayPattern' ? 'iterable' : 'object'}]`; + call = b.call('$.tag', call, b.literal(label)); + } + + return b.declarator(id, call); }), ...paths.map((path) => { const value = /** @type {Expression} */ (context.visit(path.expression)); @@ -228,19 +231,37 @@ export function VariableDeclaration(node, context) { } } else { const init = /** @type {CallExpression} */ (declarator.init); + let expression = /** @type {Expression} */ ( + context.visit(value, { + ...context.state, + in_derived: rune === '$derived' + }) + ); let rhs = value; if (rune !== '$derived' || init.arguments[0].type !== 'Identifier') { const id = b.id(context.state.scope.generate('$$d')); + let call = b.call('$.derived', rune === '$derived' ? b.thunk(expression) : expression); + rhs = b.call('$.get', id); - let expression = /** @type {Expression} */ (context.visit(value)); - if (rune === '$derived') expression = b.thunk(expression); - const call = b.call('$.derived', expression); - declarations.push( - b.declarator(id, dev ? b.call('$.tag', call, b.literal('[$derived iterable]')) : call) - ); + if (is_async) { + const location = dev && !is_ignored(init, 'await_waterfall') && locate_node(init); + call = b.call( + '$.async_derived', + b.thunk(expression, true), + location ? b.literal(location) : undefined + ); + call = b.call(b.await(b.call('$.save', call))); + } + + if (dev) { + const label = `[$derived ${declarator.id.type === 'ArrayPattern' ? 'iterable' : 'object'}]`; + call = b.call('$.tag', call, b.literal(label)); + } + + declarations.push(b.declarator(id, call)); } const { inserts, paths } = extract_paths(declarator.id, rhs); @@ -250,10 +271,14 @@ export function VariableDeclaration(node, context) { context.state.transform[id.name] = { read: get_value }; const expression = /** @type {Expression} */ (context.visit(b.thunk(value))); - const call = b.call('$.derived', expression); - declarations.push( - b.declarator(id, dev ? b.call('$.tag', call, b.literal('[$derived iterable]')) : call) - ); + let call = b.call('$.derived', expression); + + if (dev) { + const label = `[$derived ${declarator.id.type === 'ArrayPattern' ? 'iterable' : 'object'}]`; + call = b.call('$.tag', call, b.literal(label)); + } + + declarations.push(b.declarator(id, call)); } for (const path of paths) { diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived-destructured/Child.svelte b/packages/svelte/tests/runtime-runes/samples/async-derived-destructured/Child.svelte new file mode 100644 index 000000000000..39112b12a782 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-derived-destructured/Child.svelte @@ -0,0 +1,13 @@ + + + + +

{count} ** 2 = {squared}

+

{count} ** 3 = {cubed}

diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived-destructured/_config.js b/packages/svelte/tests/runtime-runes/samples/async-derived-destructured/_config.js new file mode 100644 index 000000000000..d444e8e1d956 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-derived-destructured/_config.js @@ -0,0 +1,31 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target }) { + await tick(); + + const [increment] = target.querySelectorAll('button'); + + assert.htmlEqual( + target.innerHTML, + ` + +

1 ** 2 = 1

+

1 ** 3 = 1

+ ` + ); + + increment.click(); + await tick(); + + assert.htmlEqual( + target.innerHTML, + ` + +

2 ** 2 = 4

+

2 ** 3 = 8

+ ` + ); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived-destructured/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-derived-destructured/main.svelte new file mode 100644 index 000000000000..c5d8a12a7807 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-derived-destructured/main.svelte @@ -0,0 +1,11 @@ + + + + + + {#snippet pending()} +

pending

+ {/snippet} +
diff --git a/svelte.config.js b/svelte.config.js new file mode 100644 index 000000000000..442cd7892c7b --- /dev/null +++ b/svelte.config.js @@ -0,0 +1,8 @@ +// we need this so the VS Code extension doesn't yell at us +export default { + compilerOptions: { + experimental: { + async: true + } + } +}; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

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.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy