fix: allow async destructured deriveds (#16444)

* fix: allow async destructured deriveds

* add test

* tweak

* tweak

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/16445/head
ComputerGuy 2 months ago committed by GitHub
parent 307ec228ff
commit e1e7a75d71
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: allow async destructured deriveds

@ -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) {

@ -0,0 +1,13 @@
<script>
let count = $state(1);
let { squared, cubed } = $derived(await {
squared: count ** 2,
cubed: count ** 3
});
</script>
<button onclick={() => count++}>increment</button>
<p>{count} ** 2 = {squared}</p>
<p>{count} ** 3 = {cubed}</p>

@ -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,
`
<button>increment</button>
<p>1 ** 2 = 1</p>
<p>1 ** 3 = 1</p>
`
);
increment.click();
await tick();
assert.htmlEqual(
target.innerHTML,
`
<button>increment</button>
<p>2 ** 2 = 4</p>
<p>2 ** 3 = 8</p>
`
);
}
});

@ -0,0 +1,11 @@
<script>
import Child from './Child.svelte';
</script>
<svelte:boundary>
<Child />
{#snippet pending()}
<p>pending</p>
{/snippet}
</svelte:boundary>

@ -0,0 +1,8 @@
// we need this so the VS Code extension doesn't yell at us
export default {
compilerOptions: {
experimental: {
async: true
}
}
};
Loading…
Cancel
Save