Skip to content

Commit 57ed936

Browse files
committed
fix: run deferred effects in async components
1 parent d92fa43 commit 57ed936

File tree

5 files changed

+27
-4
lines changed

5 files changed

+27
-4
lines changed

.changeset/red-spies-mix.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: run deferred effects in async components

packages/svelte/src/compiler/phases/3-transform/client/transform-client.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ export function client_component(analysis, options) {
385385
.../** @type {ESTree.Statement[]} */ (template.body)
386386
]);
387387

388-
component_block.body.push(b.stmt(b.call(`$.async_body`, b.arrow([], body, true))));
388+
component_block.body.push(b.stmt(b.call(`$.async_body`, b.arrow([], body, true), b.true)));
389389
} else {
390390
component_block.body.push(
391391
...state.instance_level_snippets,

packages/svelte/src/internal/client/context.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export function push(props, runes = false, fn) {
147147
p: component_context,
148148
c: null,
149149
e: null,
150+
a: false,
150151
s: props,
151152
x: null,
152153
l: legacy_mode_flag && !runes ? { s: null, u: null, $: [] } : null
@@ -168,7 +169,7 @@ export function pop(component) {
168169
var context = /** @type {ComponentContext} */ (component_context);
169170
var effects = context.e;
170171

171-
if (effects !== null) {
172+
if (effects !== null && context.a === false) {
172173
context.e = null;
173174

174175
for (var fn of effects) {

packages/svelte/src/internal/client/reactivity/async.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
derived_safe_equal,
2020
set_from_async_derived
2121
} from './deriveds.js';
22-
import { aborted } from './effects.js';
22+
import { aborted, create_user_effect } from './effects.js';
2323

2424
/**
2525
*
@@ -176,10 +176,15 @@ export function unset_context() {
176176

177177
/**
178178
* @param {() => Promise<void>} fn
179+
* @param {boolean} [is_component]
179180
*/
180-
export async function async_body(fn) {
181+
export async function async_body(fn, is_component = false) {
181182
var unsuspend = suspend();
182183
var active = /** @type {Effect} */ (active_effect);
184+
var ctx = is_component ? component_context : null;
185+
if (ctx !== null) {
186+
ctx.a = true;
187+
}
183188

184189
try {
185190
await fn();
@@ -189,5 +194,15 @@ export async function async_body(fn) {
189194
}
190195
} finally {
191196
unsuspend();
197+
if (ctx !== null && ctx.e !== null) {
198+
var prev = component_context;
199+
var effects = ctx.e;
200+
set_component_context(ctx);
201+
for (var effect of effects) {
202+
create_user_effect(effect);
203+
}
204+
set_component_context(prev);
205+
ctx = prev = null;
206+
}
192207
}
193208
}

packages/svelte/src/internal/client/types.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export type ComponentContext = {
1616
c: null | Map<unknown, unknown>;
1717
/** deferred effects */
1818
e: null | Array<() => void | (() => void)>;
19+
/** whether the component is suspending */
20+
a: boolean;
1921
/**
2022
* props — needed for legacy mode lifecycle functions, and for `createEventDispatcher`
2123
* @deprecated remove in 6.0

0 commit comments

Comments
 (0)