@@ -248,9 +248,10 @@ export function internal_set(source, value) {
248248/**
249249 * @param {Value } signal
250250 * @param {number } status should be DIRTY or MAYBE_DIRTY
251+ * @param {Set<Value> } [visited]
251252 * @returns {void }
252253 */
253- function mark_reactions ( signal , status ) {
254+ function mark_reactions ( signal , status , visited ) {
254255 var reactions = signal . reactions ;
255256 if ( reactions === null ) return ;
256257
@@ -265,11 +266,14 @@ function mark_reactions(signal, status) {
265266 var effect = /** @type {Effect } */ ( reaction ) ;
266267 var deriveds = effect . deriveds ;
267268 if ( deriveds !== null ) {
269+ const visited_set = visited ?? new Set ( ) ;
270+
268271 for ( let i = 0 ; i < deriveds . length ; i ++ ) {
269272 var derived = deriveds [ i ] ;
270- if ( derived . parent !== effect ) {
273+ if ( derived . parent !== effect && ! visited_set ?. has ( derived ) ) {
274+ visited_set . add ( derived )
271275 set_signal_status ( derived , DIRTY ) ;
272- mark_reactions ( derived , MAYBE_DIRTY ) ;
276+ mark_reactions ( derived , MAYBE_DIRTY , visited_set ) ;
273277 }
274278 }
275279 }
@@ -292,7 +296,7 @@ function mark_reactions(signal, status) {
292296 // If the signal a) was previously clean or b) is an unowned derived, then mark it
293297 if ( ( flags & ( CLEAN | UNOWNED ) ) !== 0 ) {
294298 if ( ( flags & DERIVED ) !== 0 ) {
295- mark_reactions ( /** @type {Derived } */ ( reaction ) , MAYBE_DIRTY ) ;
299+ mark_reactions ( /** @type {Derived } */ ( reaction ) , MAYBE_DIRTY , visited ) ;
296300 } else {
297301 effect = /** @type {Effect } */ ( reaction ) ;
298302 schedule_effect ( effect ) ;
0 commit comments