Skip to content

Commit 1125a15

Browse files
committed
Add try/catch recovery to SpawnFrameScheduler flush
1 parent 29af425 commit 1125a15

1 file changed

Lines changed: 22 additions & 7 deletions

File tree

spawn/renderer.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -300,15 +300,30 @@ export class SpawnFrameScheduler {
300300
this.dirtyComponents.clear();
301301

302302
const requestRenders = new Set<() => void>();
303+
const failed: SpawnFrameTarget[] = [];
304+
303305
for (const component of batch) {
304-
// 1. Apply accumulated event state to rendering components
305-
component.flushPendingUpdates();
306-
// 2. Invalidate render cache so render() recomputes on next TUI paint
307-
component.clearRenderCache();
308-
// 3. Collect TUI invalidate
309-
const r = component.flushScheduledRender();
310-
if (r) requestRenders.add(r);
306+
try {
307+
// 1. Apply accumulated event state to rendering components
308+
component.flushPendingUpdates();
309+
// 2. Invalidate render cache so render() recomputes on next TUI paint
310+
component.clearRenderCache();
311+
// 3. Collect TUI invalidate
312+
const r = component.flushScheduledRender();
313+
if (r) requestRenders.add(r);
314+
} catch (e) {
315+
// Component failed during flush — re-queue for next frame.
316+
// The error is logged but we continue processing remaining components.
317+
console.error("[spawn] flush error on component:", e);
318+
failed.push(component);
319+
}
311320
}
321+
322+
// Re-queue failed components for recovery on next frame
323+
for (const component of failed) {
324+
getSingletons().frameScheduler.markDirty(component);
325+
}
326+
312327
// One invalidate per distinct callback per frame tick.
313328
for (const requestRender of requestRenders) {
314329
requestRender();

0 commit comments

Comments
 (0)