@@ -11,7 +11,8 @@ import {
1111 RENDER_EFFECT ,
1212 ROOT_EFFECT ,
1313 MAYBE_DIRTY ,
14- DERIVED
14+ DERIVED ,
15+ BOUNDARY_EFFECT
1516} from '#client/constants' ;
1617import { async_mode_flag } from '../../flags/index.js' ;
1718import { deferred , define_property } from '../../shared/utils.js' ;
@@ -30,6 +31,16 @@ import { invoke_error_boundary } from '../error-handling.js';
3031import { old_values } from './sources.js' ;
3132import { unlink_effect } from './effects.js' ;
3233
34+ /**
35+ * @typedef {{
36+ * parent: EffectTarget | null;
37+ * effect: Effect | null;
38+ * effects: Effect[];
39+ * render_effects: Effect[];
40+ * block_effects: Effect[];
41+ * }} EffectTarget
42+ */
43+
3344/** @type {Set<Batch> } */
3445const batches = new Set ( ) ;
3546
@@ -97,26 +108,6 @@ export class Batch {
97108 */
98109 #deferred = null ;
99110
100- /**
101- * Template effects and `$effect.pre` effects, which run when
102- * a batch is committed
103- * @type {Effect[] }
104- */
105- #render_effects = [ ] ;
106-
107- /**
108- * The same as `#render_effects`, but for `$effect` (which runs after)
109- * @type {Effect[] }
110- */
111- #effects = [ ] ;
112-
113- /**
114- * Block effects, which may need to re-run on subsequent flushes
115- * in order to update internal sources (e.g. each block items)
116- * @type {Effect[] }
117- */
118- #block_effects = [ ] ;
119-
120111 /**
121112 * Deferred effects (which run after async work has completed) that are DIRTY
122113 * @type {Effect[] }
@@ -155,33 +146,26 @@ export class Batch {
155146 if ( this . #pending === 0 ) {
156147 // TODO we need this because we commit _then_ flush effects...
157148 // maybe there's a way we can reverse the order?
158- var previous_batch_sources = batch_values ;
149+ // var previous_batch_sources = batch_values;
159150
160151 this . #commit( ) ;
161152
162- var render_effects = this . #render_effects;
163- var effects = this . #effects;
164-
165- this . #render_effects = [ ] ;
166- this . #effects = [ ] ;
167- this . #block_effects = [ ] ;
168-
169153 // If sources are written to, then work needs to happen in a separate batch, else prior sources would be mixed with
170154 // newly updated sources, which could lead to infinite loops when effects run over and over again.
171155 previous_batch = this ;
172156 current_batch = null ;
173157
174- batch_values = previous_batch_sources ;
175- flush_queued_effects ( render_effects ) ;
176- flush_queued_effects ( effects ) ;
158+ // batch_values = previous_batch_sources;
159+ // flush_queued_effects(target. render_effects);
160+ // flush_queued_effects(target. effects);
177161
178162 previous_batch = null ;
179163
180164 this . #deferred?. resolve ( ) ;
181165 } else {
182- this . #defer_effects( this . # render_effects) ;
183- this . #defer_effects( this . # effects) ;
184- this . #defer_effects( this . # block_effects) ;
166+ // this.#defer_effects(target. render_effects);
167+ // this.#defer_effects(target. effects);
168+ // this.#defer_effects(target. block_effects);
185169 }
186170
187171 batch_values = null ;
@@ -195,6 +179,17 @@ export class Batch {
195179 #traverse_effect_tree( root ) {
196180 root . f ^= CLEAN ;
197181
182+ var should_defer = false ;
183+
184+ /** @type {EffectTarget } */
185+ var target = {
186+ parent : null ,
187+ effect : null ,
188+ effects : [ ] ,
189+ render_effects : [ ] ,
190+ block_effects : [ ]
191+ } ;
192+
198193 var effect = root . first ;
199194
200195 while ( effect !== null ) {
@@ -204,15 +199,25 @@ export class Batch {
204199
205200 var skip = is_skippable_branch || ( flags & INERT ) !== 0 || this . skipped_effects . has ( effect ) ;
206201
202+ if ( ( effect . f & BOUNDARY_EFFECT ) !== 0 && effect . b ?. is_pending ( ) ) {
203+ target = {
204+ parent : target ,
205+ effect,
206+ effects : [ ] ,
207+ render_effects : [ ] ,
208+ block_effects : [ ]
209+ } ;
210+ }
211+
207212 if ( ! skip && effect . fn !== null ) {
208213 if ( is_branch ) {
209214 effect . f ^= CLEAN ;
210215 } else if ( ( flags & EFFECT ) !== 0 ) {
211- this . # effects. push ( effect ) ;
216+ target . effects . push ( effect ) ;
212217 } else if ( async_mode_flag && ( flags & RENDER_EFFECT ) !== 0 ) {
213- this . # render_effects. push ( effect ) ;
218+ target . render_effects . push ( effect ) ;
214219 } else if ( is_dirty ( effect ) ) {
215- if ( ( effect . f & BLOCK_EFFECT ) !== 0 ) this . # block_effects. push ( effect ) ;
220+ if ( ( effect . f & BLOCK_EFFECT ) !== 0 ) target . block_effects . push ( effect ) ;
216221 update_effect ( effect ) ;
217222 }
218223
@@ -228,10 +233,41 @@ export class Batch {
228233 effect = effect . next ;
229234
230235 while ( effect === null && parent !== null ) {
236+ if ( parent . b !== null ) {
237+ var ready = parent . b . local_pending_count === 0 ;
238+
239+ if ( target . parent === null ) {
240+ should_defer ||= ! ready ;
241+ } else if ( parent === target . effect ) {
242+ if ( ready ) {
243+ // TODO can this happen?
244+ target . parent . effects . push ( ...target . effects ) ;
245+ target . parent . render_effects . push ( ...target . render_effects ) ;
246+ target . parent . block_effects . push ( ...target . block_effects ) ;
247+ } else {
248+ this . #defer_effects( target . effects ) ;
249+ this . #defer_effects( target . render_effects ) ;
250+ this . #defer_effects( target . block_effects ) ;
251+ }
252+
253+ target = /** @type {EffectTarget } */ ( target . parent ) ;
254+ }
255+ }
256+
231257 effect = parent . next ;
232258 parent = parent . parent ;
233259 }
234260 }
261+
262+ if ( should_defer ) {
263+ this . #defer_effects( target . effects ) ;
264+ this . #defer_effects( target . render_effects ) ;
265+ this . #defer_effects( target . block_effects ) ;
266+ } else {
267+ // TODO append/detach blocks here as well
268+ flush_queued_effects ( target . render_effects ) ;
269+ flush_queued_effects ( target . effects ) ;
270+ }
235271 }
236272
237273 /**
@@ -245,8 +281,6 @@ export class Batch {
245281 // mark as clean so they get scheduled if they depend on pending async state
246282 set_signal_status ( e , CLEAN ) ;
247283 }
248-
249- effects . length = 0 ;
250284 }
251285
252286 /**
0 commit comments