File tree Expand file tree Collapse file tree 5 files changed +92
-5
lines changed
src/internal/client/reactivity
tests/runtime-runes/samples
async-block-reject-each-during-init
async-top-level-error-nested-obsolete Expand file tree Collapse file tree 5 files changed +92
-5
lines changed Original file line number Diff line number Diff line change @@ -344,6 +344,48 @@ export class Batch {
344344 current_batch = this ;
345345 }
346346
347+ /**
348+ * Check if the branch this effect is in is obsolete in a later batch.
349+ * That is, if the branch exists in this batch but will be destroyed in a later batch.
350+ * @param {Effect } effect
351+ */
352+ branch_obsolete ( effect ) {
353+ /** @type {Effect[] } */
354+ let alive = [ ] ;
355+ /** @type {Effect[] } */
356+ let skipped = [ ] ;
357+ /** @type {Effect | null } */
358+ let current = effect ;
359+
360+ while ( current !== null ) {
361+ if ( ( current . f & ( BRANCH_EFFECT | ROOT_EFFECT ) ) !== 0 ) {
362+ alive . push ( current ) ;
363+ if ( this . skipped_effects . has ( current ) ) {
364+ skipped . push ( ...alive ) ;
365+ alive = [ ] ;
366+ }
367+ }
368+ current = current . parent ;
369+ }
370+
371+ let check = false ;
372+ for ( const b of batches ) {
373+ if ( b === this ) {
374+ check = true ;
375+ } else if ( check ) {
376+ if (
377+ alive . some ( ( branch ) => b . skipped_effects . has ( branch ) ) ||
378+ // TODO do we even have to check skipped here? how would an async_derived run for a branch that was already skipped?
379+ ( skipped . length > 0 && ! skipped . some ( ( branch ) => b . skipped_effects . has ( branch ) ) )
380+ ) {
381+ return true ;
382+ }
383+ }
384+ }
385+
386+ return false ;
387+ }
388+
347389 deactivate ( ) {
348390 current_batch = null ;
349391 previous_batch = null ;
Original file line number Diff line number Diff line change @@ -115,7 +115,7 @@ export function async_derived(fn, location) {
115115 // only suspend in async deriveds created on initialisation
116116 var should_suspend = ! active_reaction ;
117117
118- async_effect ( ( ) => {
118+ var effect = async_effect ( ( ) => {
119119 if ( DEV ) current_async_effect = active_effect ;
120120
121121 try {
@@ -153,7 +153,7 @@ export function async_derived(fn, location) {
153153 batch . activate ( ) ;
154154
155155 if ( error ) {
156- if ( error !== STALE_REACTION ) {
156+ if ( error !== STALE_REACTION && ! batch . branch_obsolete ( effect ) ) {
157157 signal . f |= ERROR_VALUE ;
158158
159159 // @ts -expect-error the error is the wrong type, but we don't care
Original file line number Diff line number Diff line change @@ -8,9 +8,11 @@ export default test({
88 increment . click ( ) ;
99 await tick ( ) ;
1010
11+ reject . click ( ) ;
1112 reject . click ( ) ;
1213 await tick ( ) ;
1314
15+ resolve . click ( ) ;
1416 resolve . click ( ) ;
1517 await tick ( ) ;
1618
@@ -22,6 +24,35 @@ export default test({
2224 <button>reject</button>
2325 <p>false</p>
2426 <p>1</p>
27+ <p>false</p>
28+ <p>1</p>
29+ `
30+ ) ;
31+
32+ increment . click ( ) ;
33+ await tick ( ) ;
34+
35+ increment . click ( ) ;
36+ await tick ( ) ;
37+
38+ reject . click ( ) ;
39+ reject . click ( ) ;
40+ await tick ( ) ;
41+
42+ resolve . click ( ) ;
43+ resolve . click ( ) ;
44+ await tick ( ) ;
45+
46+ assert . htmlEqual (
47+ target . innerHTML ,
48+ `
49+ <button>increment</button>
50+ <button>resolve</button>
51+ <button>reject</button>
52+ <p>false</p>
53+ <p>3</p>
54+ <p>false</p>
55+ <p>3</p>
2556 `
2657 ) ;
2758 }
Original file line number Diff line number Diff line change 33
44 let deferreds = [];
55
6- function push () {
6+ function push (_just_so_that_template_is_reactive_ ) {
77 const deferred = Promise .withResolvers ();
88 deferreds .push (deferred);
99 return deferred .promise ;
1717<svelte:boundary >
1818 {#if count % 2 === 0 }
1919 <p >true</p >
20- {#each await push () as count }<p >{count }</p >{/each }
20+ {#each await push (count ) as count }<p >{count }</p >{/each }
2121 {:else }
2222 <p >false</p >
23- {#each await push () as count }<p >{count }</p >{/each }
23+ {#each await push (count ) as count }<p >{count }</p >{/each }
24+ {/if }
25+
26+ {#if count % 2 === 0 }
27+ <p >true</p >
28+ {#each await push (count ) as count }<p >{count }</p >{/each }
29+ {/if }
30+ {#if count % 2 === 1 }
31+ <p >false</p >
32+ {#each await push (count ) as count }<p >{count }</p >{/each }
2433 {/if }
2534
2635 {#snippet pending ()}
Original file line number Diff line number Diff line change 33 export let route = $state ({ current: ' home' });
44 </script >
55
6+ <script >
7+ // reset from earlier tests
8+ route .current = ' home'
9+ </script >
10+
611<button onclick ={() => route .reject ()}>reject</button >
712
813<svelte:boundary >
You can’t perform that action at this time.
0 commit comments