@@ -35,7 +35,8 @@ const ASYNC_DECREMENT = Symbol();
3535
3636/**
3737 * @param {Effect } boundary
38- * @param {() => void } fn
38+ * @param {() => Effect | null } fn
39+ * @returns {Effect | null }
3940 */
4041function with_boundary ( boundary , fn ) {
4142 var previous_effect = active_effect ;
@@ -47,7 +48,7 @@ function with_boundary(boundary, fn) {
4748 set_component_context ( boundary . ctx ) ;
4849
4950 try {
50- fn ( ) ;
51+ return fn ( ) ;
5152 } finally {
5253 set_active_effect ( previous_effect ) ;
5354 set_active_reaction ( previous_reaction ) ;
@@ -69,11 +70,14 @@ export function boundary(node, props, children) {
6970 var anchor = node ;
7071
7172 block ( ( ) => {
72- /** @type {Effect } */
73- var boundary_effect ;
73+ /** @type {Effect | null } */
74+ var main_effect = null ;
75+
76+ /** @type {Effect | null } */
77+ var pending_effect = null ;
7478
7579 /** @type {Effect | null } */
76- var offscreen_effect = null ;
80+ var failed_effect = null ;
7781
7882 /** @type {DocumentFragment | null } */
7983 var offscreen_fragment = null ;
@@ -85,32 +89,33 @@ export function boundary(node, props, children) {
8589
8690 /**
8791 * @param {() => void } snippet_fn
92+ * @returns {Effect | null }
8893 */
8994 function render_snippet ( snippet_fn ) {
90- with_boundary ( boundary , ( ) => {
95+ return with_boundary ( boundary , ( ) => {
9196 is_creating_fallback = true ;
9297
9398 try {
94- boundary_effect = branch ( snippet_fn ) ;
99+ return branch ( snippet_fn ) ;
95100 } catch ( error ) {
96101 handle_error ( error , boundary , null , boundary . ctx ) ;
102+ return null ;
103+ } finally {
104+ reset_is_throwing_error ( ) ;
105+ is_creating_fallback = false ;
97106 }
98-
99- reset_is_throwing_error ( ) ;
100- is_creating_fallback = false ;
101107 } ) ;
102108 }
103109
104110 function suspend ( ) {
105- if ( offscreen_effect || ! boundary_effect ) {
111+ if ( offscreen_fragment || ! main_effect ) {
106112 return ;
107113 }
108114
109- var effect = boundary_effect ;
110- offscreen_effect = boundary_effect ;
115+ var effect = main_effect ;
111116
112117 pause_effect (
113- boundary_effect ,
118+ effect ,
114119 ( ) => {
115120 var node = effect . nodes_start ;
116121 var end = effect . nodes_end ;
@@ -131,34 +136,40 @@ export function boundary(node, props, children) {
131136 const pending = props . pending ;
132137
133138 if ( pending ) {
134- render_snippet ( ( ) => {
135- pending ( anchor ) ;
136- } ) ;
139+ pending_effect = render_snippet ( ( ) => pending ( anchor ) ) ;
137140 }
138141 }
139142
140143 function unsuspend ( ) {
141- if ( ! offscreen_effect ) {
144+ if ( ! offscreen_fragment ) {
142145 return ;
143146 }
144147
145- if ( boundary_effect ) {
146- destroy_effect ( boundary_effect ) ;
148+ if ( pending_effect !== null ) {
149+ pause_effect ( pending_effect ) ;
147150 }
148151
149- boundary_effect = offscreen_effect ;
150- offscreen_effect = null ;
151152 anchor . before ( /** @type {DocumentFragment } */ ( offscreen_fragment ) ) ;
152- resume_effect ( boundary_effect ) ;
153+ offscreen_fragment = null ;
154+
155+ if ( main_effect !== null ) {
156+ resume_effect ( main_effect ) ;
157+ }
153158 }
154159
155160 function reset ( ) {
156- pause_effect ( boundary_effect ) ;
161+ if ( failed_effect !== null ) {
162+ pause_effect ( failed_effect ) ;
163+ }
157164
158- with_boundary ( boundary , ( ) => {
165+ main_effect = with_boundary ( boundary , ( ) => {
159166 is_creating_fallback = false ;
160- boundary_effect = branch ( ( ) => children ( anchor ) ) ;
161- reset_is_throwing_error ( ) ;
167+
168+ try {
169+ return branch ( ( ) => children ( anchor ) ) ;
170+ } finally {
171+ reset_is_throwing_error ( ) ;
172+ }
162173 } ) ;
163174 }
164175
@@ -192,17 +203,23 @@ export function boundary(node, props, children) {
192203
193204 onerror ?. ( error , reset ) ;
194205
195- if ( boundary_effect ) {
196- destroy_effect ( boundary_effect ) ;
197- } else if ( hydrating ) {
206+ if ( main_effect ) {
207+ destroy_effect ( main_effect ) ;
208+ }
209+
210+ if ( failed_effect ) {
211+ destroy_effect ( failed_effect ) ;
212+ }
213+
214+ if ( hydrating ) {
198215 set_hydrate_node ( hydrate_open ) ;
199216 next ( ) ;
200217 set_hydrate_node ( remove_nodes ( ) ) ;
201218 }
202219
203220 if ( failed ) {
204221 queue_boundary_micro_task ( ( ) => {
205- render_snippet ( ( ) => {
222+ failed_effect = render_snippet ( ( ) => {
206223 failed (
207224 anchor ,
208225 ( ) => error ,
@@ -223,7 +240,7 @@ export function boundary(node, props, children) {
223240 const pending = props . pending ;
224241
225242 if ( hydrating && pending ) {
226- boundary_effect = branch ( ( ) => pending ( anchor ) ) ;
243+ pending_effect = branch ( ( ) => pending ( anchor ) ) ;
227244
228245 // ...now what? we need to start rendering `boundary_fn` offscreen,
229246 // and either insert the resulting fragment (if nothing suspends)
@@ -235,13 +252,14 @@ export function boundary(node, props, children) {
235252 // the pending or main block was rendered for a given
236253 // boundary, and hydrate accordingly
237254 queueMicrotask ( ( ) => {
238- destroy_effect ( boundary_effect ) ;
239- with_boundary ( boundary , ( ) => {
240- boundary_effect = branch ( ( ) => children ( anchor ) ) ;
255+ destroy_effect ( /** @type {Effect } */ ( pending_effect ) ) ;
256+
257+ main_effect = with_boundary ( boundary , ( ) => {
258+ return branch ( ( ) => children ( anchor ) ) ;
241259 } ) ;
242260 } ) ;
243261 } else {
244- boundary_effect = branch ( ( ) => children ( anchor ) ) ;
262+ main_effect = branch ( ( ) => children ( anchor ) ) ;
245263 }
246264
247265 reset_is_throwing_error ( ) ;
0 commit comments