renderable: defer layout for late children (#1545)

Yoga can report NaN dimensions for nodes attached after a layout pass.
Keep their prior size until the next pass provides valid dimensions.

Because NaN != NaN, this caused continues rerender and CPU hog.

Issue #1543
This commit is contained in:
Simon Klee authored and GitHub committed 2026-09-30 07:04:48 +02:00
1 parent 8742fa72b9
commit 89bdbb6d64
2 files changed
+16 -2

No files matched your search

+4 -2
View File
@@ -1109,8 +1109,10 @@ export abstract class Renderable extends BaseRenderable {
this._screenX = parentScreenX + this._x + this._translateX
this._screenY = parentScreenY + this._y + this._translateY
const newWidth = Math.max(layout.width, 1)
const newHeight = Math.max(layout.height, 1)
// Yoga reports NaN for a node attached after this frame's layout pass.
// Keep the last size until the next pass lays the node out.
const newWidth = Number.isNaN(layout.width) ? oldWidth : Math.max(layout.width, 1)
const newHeight = Number.isNaN(layout.height) ? oldHeight : Math.max(layout.height, 1)
const sizeChanged = oldWidth !== newWidth || oldHeight !== newHeight
this._widthValue = newWidth
@@ -890,6 +890,18 @@ describe("Renderable - Child Management", () => {
expect(grandchild.height).toBeGreaterThan(0)
})
test("child added during the layout pass is sized by the next pass", async () => {
const sizes: number[][] = []
const child = new TestRenderable(testRenderer, { flexGrow: 1, onSizeChange: () => sizes.push([child.width]) })
const parent = new TestRenderable(testRenderer, { width: "100%", onSizeChange: () => parent.add(child) })
testRenderer.root.add(parent)
await renderOnce()
await renderOnce()
expect(sizes).toEqual([[testRenderer.width]])
})
test("children added via insertBefore receive correct layout on first render", async () => {
const parent = new TestRenderable(testRenderer, {
id: "parent",