Skip to content

[IMP] owl-runtime: detect render loops instead of freezing#1969

Merged
mcm-odoo merged 1 commit into
masterfrom
issue-1968-ged
Jun 30, 2026
Merged

[IMP] owl-runtime: detect render loops instead of freezing#1969
mcm-odoo merged 1 commit into
masterfrom
issue-1968-ged

Conversation

@ged-odoo

Copy link
Copy Markdown
Contributor

When a component updates reactive state that an ancestor reads during render (e.g. a child whose setup() calls a parent state setter), the parent re-renders, recreates the child, runs setup() again, and so on. The cycle is driven entirely by microtasks, so the rAF-based DOM commit never runs and the tab freezes silently with no error, which is very hard to debug.

Track how many times a root fiber is re-rendered before being committed to the DOM (renderCount, bumped in makeRootFiber when an uncommitted fiber is recycled). A healthy render commits and discards its fiber, so a fresh one always starts at 0; only a self-retriggering loop ever makes the count climb without bound. Once it exceeds MAX_RENDER_ITERATIONS, Fiber.render() bails through handleError with a clear OwlError naming the looping component, halting the loop and tearing the app down. Same idea as React's "Maximum update depth exceeded" / Vue's "Maximum recursive updates", adapted to Owl's async fiber model.

closes #1968

When a component updates reactive state that an ancestor reads during
render (e.g. a child whose setup() calls a parent state setter), the
parent re-renders, recreates the child, runs setup() again, and so on.
The cycle is driven entirely by microtasks, so the rAF-based DOM commit
never runs and the tab freezes silently with no error, which is very
hard to debug.

Track how many times a root fiber is re-rendered before being committed
to the DOM (renderCount, bumped in makeRootFiber when an uncommitted
fiber is recycled). A healthy render commits and discards its fiber, so
a fresh one always starts at 0; only a self-retriggering loop ever makes
the count climb without bound. Once it exceeds MAX_RENDER_ITERATIONS,
Fiber.render() bails through handleError with a clear OwlError naming the
looping component, halting the loop and tearing the app down. Same idea
as React's "Maximum update depth exceeded" / Vue's "Maximum recursive
updates", adapted to Owl's async fiber model.

closes #1968
@mcm-odoo mcm-odoo merged commit 8f791a4 into master Jun 30, 2026
2 checks passed
@mcm-odoo mcm-odoo deleted the issue-1968-ged branch June 30, 2026 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

render loops are hard to debug

2 participants