File tree Expand file tree Collapse file tree 4 files changed +95
-2
lines changed
src/internal/client/reactivity
tests/runtime-runes/samples/async-stale-derived Expand file tree Collapse file tree 4 files changed +95
-2
lines changed Original file line number Diff line number Diff line change @@ -87,6 +87,12 @@ export class Batch {
8787 */
8888 #deferred = null ;
8989
90+ /**
91+ * True if an async effect inside this batch resolved and
92+ * its parent branch was already deleted
93+ */
94+ #neutered = false ;
95+
9096 /**
9197 * Async effects (created inside `async_derived`) encountered during processing.
9298 * These run after the rest of the batch has updated, since they should
@@ -278,10 +284,14 @@ export class Batch {
278284 current_batch = null ;
279285 }
280286
287+ neuter ( ) {
288+ this . #neutered = true ;
289+ }
290+
281291 flush ( ) {
282292 if ( queued_root_effects . length > 0 ) {
283293 this . flush_effects ( ) ;
284- } else {
294+ } else if ( ! this . #neutered ) {
285295 this . #commit( ) ;
286296 }
287297
Original file line number Diff line number Diff line change 99 EFFECT_PRESERVED ,
1010 MAYBE_DIRTY ,
1111 STALE_REACTION ,
12- UNOWNED
12+ UNOWNED ,
13+ DESTROYED
1314} from '#client/constants' ;
1415import {
1516 active_reaction ,
@@ -144,6 +145,10 @@ export function async_derived(fn, location) {
144145 const handler = ( value , error = undefined ) => {
145146 prev = null ;
146147
148+ if ( ( parent . f & DESTROYED ) !== 0 ) {
149+ batch . neuter ( ) ;
150+ }
151+
147152 current_async_effect = null ;
148153
149154 if ( ! pending ) batch . activate ( ) ;
Original file line number Diff line number Diff line change 1+ import { tick } from 'svelte' ;
2+ import { test } from '../../test' ;
3+
4+ export default test ( {
5+ async test ( { assert, target } ) {
6+ await tick ( ) ;
7+
8+ const [ increment , shift ] = target . querySelectorAll ( 'button' ) ;
9+
10+ assert . htmlEqual (
11+ target . innerHTML ,
12+ `
13+ <button>increment</button>
14+ <button>shift</button>
15+ <p>0</p>
16+ `
17+ ) ;
18+
19+ increment . click ( ) ;
20+ await tick ( ) ;
21+
22+ increment . click ( ) ;
23+ await tick ( ) ;
24+
25+ increment . click ( ) ;
26+ await tick ( ) ;
27+
28+ shift . click ( ) ;
29+ await tick ( ) ;
30+
31+ assert . htmlEqual (
32+ target . innerHTML ,
33+ `
34+ <button>increment</button>
35+ <button>shift</button>
36+ <p>2</p>
37+ `
38+ ) ;
39+
40+ shift . click ( ) ;
41+ await tick ( ) ;
42+
43+ assert . htmlEqual (
44+ target . innerHTML ,
45+ `
46+ <button>increment</button>
47+ <button>shift</button>
48+ <p>delayed: 3</p>
49+ `
50+ ) ;
51+ }
52+ } ) ;
Original file line number Diff line number Diff line change 1+ <script lang =" ts" >
2+ let count = $state (0 );
3+
4+ let deferreds = [];
5+
6+ function push() {
7+ const deferred = Promise .withResolvers ();
8+ deferreds .push (deferred );
9+ return deferred .promise ;
10+ }
11+ </script >
12+
13+ <button onclick ={() => count += 1 }>increment</button >
14+ <button onclick ={() => deferreds .shift ()?.resolve (count )}>shift</button >
15+
16+ <svelte:boundary >
17+ {#if count % 2 }
18+ <p >delayed: {await push ()}</p >
19+ {:else }
20+ <p >{await count }</p >
21+ {/if }
22+
23+ {#snippet pending ()}
24+ <p >loading...</p >
25+ {/ snippet }
26+ </svelte:boundary >
You can’t perform that action at this time.
0 commit comments