File tree Expand file tree Collapse file tree
src/internal/client/reactivity
tests/runtime-runes/samples/async-reactivity-loss-for-await-break-return Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ ---
2+ ' svelte ' : patch
3+ ---
4+
5+ fix: properly invoke ` iterator.return() ` during reactivity loss check
Original file line number Diff line number Diff line change @@ -209,8 +209,8 @@ export async function* for_await_track_reactivity_loss(iterable) {
209209 yield value ;
210210 }
211211 } finally {
212- // If the iterator had a normal completion and `return` is defined on the iterator, call it and return the value
213- if ( normal_completion && iterator . return !== undefined ) {
212+ // If the iterator had an abrupt completion and `return` is defined on the iterator, call it and return the value
213+ if ( ! normal_completion && iterator . return !== undefined ) {
214214 // eslint-disable-next-line no-unsafe-finally
215215 return /** @type {TReturn } */ ( ( await track_reactivity_loss ( iterator . return ( ) ) ) ( ) . value ) ;
216216 }
Original file line number Diff line number Diff line change 1+ import { tick } from 'svelte' ;
2+ import { test } from '../../test' ;
3+ import { normalise_trace_logs } from '../../../helpers.js' ;
4+
5+ export default test ( {
6+ compileOptions : {
7+ dev : true
8+ } ,
9+ html : '<p>pending</p>' ,
10+ async test ( { assert, target, warnings } ) {
11+ await tick ( ) ;
12+
13+ assert . htmlEqual ( target . innerHTML , '<h1>number -> number -> number -> return -> ended</h1>' ) ;
14+
15+ assert . deepEqual ( normalise_trace_logs ( warnings ) , [
16+ {
17+ log : 'Detected reactivity loss when reading `values.length`. This happens when state is read in an async function after an earlier `await`'
18+ }
19+ ] ) ;
20+ }
21+ } ) ;
Original file line number Diff line number Diff line change 1+ <script >
2+ let values = $state ([0 , 1 , 2 ]);
3+
4+ async function get_result () {
5+ const logs = [];
6+
7+ const iterator = {
8+ index: 0 ,
9+ async next () {
10+ if (this .index >= values .length ) return { done: true };
11+ return { done: false , value: values[this .index ++ ] };
12+ },
13+ async return () {
14+ logs .push (' return' );
15+ return { done: true };
16+ },
17+ [Symbol .asyncIterator ]() {
18+ return this ;
19+ }
20+ };
21+
22+ for await (const value of iterator ) {
23+ logs .push (' number' );
24+ // read reactive state after async iterator await
25+ if (values .length === 3 && value === 2 ) {
26+ break ;
27+ }
28+ }
29+
30+ logs .push (' ended' );
31+ return logs .join (' -> ' );
32+ }
33+ </script >
34+
35+ <svelte:boundary >
36+ <h1 >{await get_result ()}</h1 >
37+
38+ {#snippet pending ()}
39+ <p >pending</p >
40+ {/ snippet }
41+ </svelte:boundary >
You can’t perform that action at this time.
0 commit comments