svelte
svelte copied to clipboard
Accessing an async derived in a derived declared before the async derived throws an un-descriptive error
Describe the bug
This code
<script>
function get(){
return b;
}
const a = $derived(get());
const b = $derived(await 42);
</script>
{a}
throws a Cannot read properties of undefined (reading 'f') in <unknown> in __wrapper.svelte
because when it tries to get b since b it's an async derived it's not initialized yet by the time the function for a executes. We should at least throw a more descriptive error (or possibly fix this).
Reproduction
Logs
System Info
repl
Severity
annoyance
This is caused by out-of-order rendering:
right now, if you write a component like this
<script>
function get(){
return b;
}
const b = $derived(await 42);
</script>
{get()}
it is converted to this
import 'svelte/internal/disclose-version';
import 'svelte/internal/flags/async';
import * as $ from 'svelte/internal/client';
export default function App($$anchor) {
function get() {
return $.get(b);
}
var b;
var $$promises = $.run([async () => b = await $.async_derived(() => 42)]);
$.next();
var text = $.text();
$.template_effect(($0) => $.set_text(text, $0), [get], void 0, [$$promises[0]]);
$.append($$anchor, text);
}
correctly identifying that get has $$promises[0] as a blocker, but if I put get() in a derived
<script>
function get(){
return b;
}
const a = $derived(get());
const b = $derived(await 42);
</script>
{a}
it gets converted to this
import 'svelte/internal/disclose-version';
import 'svelte/internal/flags/async';
import * as $ from 'svelte/internal/client';
export default function App($$anchor) {
function get() {
return $.get(b);
}
const a = $.derived(get);
var b;
var $$promises = $.run([async () => b = await $.async_derived(() => 42)]);
$.next();
var text = $.text();
$.template_effect(() => $.set_text(text, $.get(a)));
$.append($$anchor, text);
}
And the blocker is not there, leading to a runtime error.
Trying to fix this but I dunno if I will succeed :D