fix: better code generation for const tags with async dependencies (#17518)

pull/17522/head
Rich Harris 7 months ago committed by GitHub
parent d95887deb6
commit f9cc2d25b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: better code generation for const tags with async dependencies

@ -1,4 +1,4 @@
/** @import { Pattern } from 'estree' */
/** @import { Expression, Identifier, Pattern } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */
/** @import { ExpressionMetadata } from '../../../nodes.js' */
@ -88,8 +88,8 @@ export function ConstTag(node, context) {
/**
* @param {ComponentContext['state']} state
* @param {import('estree').Identifier} id
* @param {import('estree').Expression} expression
* @param {Identifier} id
* @param {Expression} expression
* @param {ExpressionMetadata} metadata
* @param {import('#compiler').Binding[]} bindings
*/
@ -99,7 +99,9 @@ function add_const_declaration(state, id, expression, metadata, bindings) {
const after = dev ? [b.stmt(b.call('$.get', id))] : [];
const has_await = metadata.has_await;
const blockers = [...metadata.dependencies].map((dep) => dep.blocker).filter((b) => b !== null);
const blockers = [...metadata.dependencies]
.map((dep) => dep.blocker)
.filter((b) => b !== null && b.object !== state.async_consts?.id);
if (has_await || state.async_consts || blockers.length > 0) {
const run = (state.async_consts ??= {
@ -112,7 +114,11 @@ function add_const_declaration(state, id, expression, metadata, bindings) {
const assignment = b.assignment('=', id, expression);
const body = after.length === 0 ? assignment : b.block([b.stmt(assignment), ...after]);
if (blockers.length > 0) run.thunks.push(b.thunk(b.call('Promise.all', b.array(blockers))));
if (blockers.length === 1) {
run.thunks.push(b.thunk(/** @type {Expression} */ (blockers[0])));
} else if (blockers.length > 0) {
run.thunks.push(b.thunk(b.call('Promise.all', b.array(blockers))));
}
run.thunks.push(b.thunk(body, has_await));

@ -15,7 +15,7 @@ export function ConstTag(node, context) {
const has_await = node.metadata.expression.has_await;
const blockers = [...node.metadata.expression.dependencies]
.map((dep) => dep.blocker)
.filter((b) => b !== null);
.filter((b) => b !== null && b.object !== context.state.async_consts?.id);
if (has_await || context.state.async_consts || blockers.length > 0) {
const run = (context.state.async_consts ??= {
@ -30,7 +30,9 @@ export function ConstTag(node, context) {
context.state.init.push(b.let(identifier.name));
}
if (blockers.length > 0) {
if (blockers.length === 1) {
run.thunks.push(b.thunk(/** @type {Expression} */ (blockers[0])));
} else if (blockers.length > 0) {
run.thunks.push(b.thunk(b.call('Promise.all', b.array(blockers))));
}

@ -0,0 +1,3 @@
import { test } from '../../test';
export default test({ compileOptions: { experimental: { async: true } } });

@ -0,0 +1,35 @@
import 'svelte/internal/disclose-version';
import 'svelte/internal/flags/async';
import * as $ from 'svelte/internal/client';
var root_1 = $.from_html(`<p> </p>`);
export default function Async_const($$anchor) {
var fragment = $.comment();
var node = $.first_child(fragment);
{
var consequent = ($$anchor) => {
let a;
let b;
var promises = $.run([
async () => a = (await $.save($.async_derived(async () => (await $.save(1))())))(),
() => b = $.derived(() => $.get(a) + 1)
]);
var p = root_1();
var text = $.child(p, true);
$.reset(p);
$.template_effect(() => $.set_text(text, $.get(b)), void 0, void 0, [promises[1]]);
$.append($$anchor, p);
};
$.if(node, ($$render) => {
if (true) $$render(consequent);
});
}
$.append($$anchor, fragment);
}

@ -0,0 +1,33 @@
import 'svelte/internal/flags/async';
import * as $ from 'svelte/internal/server';
export default function Async_const($$renderer) {
if (true) {
$$renderer.push('<!--[-->');
let a;
let b;
var promises = $$renderer.run([
async () => {
a = (await $.save(1))();
},
() => {
b = a + 1;
}
]);
$$renderer.push(`<p>`);
$$renderer.async([promises[1]], ($$renderer) => {
$$renderer.push(() => $.escape(b));
});
$$renderer.push(`</p>`);
} else {
$$renderer.push('<!--[!-->');
}
$$renderer.push(`<!--]-->`);
}

@ -0,0 +1,6 @@
{#if true}
{@const a = await 1}
{@const b = a + 1}
<p>{b}</p>
{/if}
Loading…
Cancel
Save