@@ -214,6 +214,51 @@ These behaviors are guaranteed by the current layout engine and validation pipel
214214- If both ` width ` and ` height ` are already resolved, ` aspectRatio ` does not override them.
215215- After derivation, min/max constraints clamp the chosen size, then final size is capped by available bounds and non-negative clamping.
216216
217+ ## Layout Stability & Caching
218+
219+ ### Stability signatures (commit-time relayout checks)
220+
221+ - On commit turns with ` checkLayoutStability: true ` , the renderer compares per-instance layout signatures against the previous committed tree.
222+ - Signature coverage is currently limited to: ` text ` , ` button ` , ` input ` , ` spacer ` , ` divider ` , ` row ` , ` column ` , and ` box ` .
223+ - ` row ` /` column ` signatures include layout constraints, spacing, ` pad ` , ` gap ` , ` align ` , ` justify ` , ` items ` , and child order (child instance ID sequence).
224+ - ` box ` signatures include layout constraints, spacing, border/title props, and child order.
225+ - ` text ` /` button ` /` input ` signatures track intrinsic width inputs (` text ` + ` maxWidth ` , button ` label ` + ` px ` , input ` value ` ).
226+
227+ Intentionally excluded:
228+
229+ - Render-only/style props are excluded from signature checks.
230+ - Routing/identity-only props that do not affect geometry (for example ` button ` ` id ` ) are excluded.
231+ - Text is tracked by width impact, not full content identity; equal-width edits do not force relayout.
232+
233+ Conservative fallback:
234+
235+ - Unsupported widget kinds or unhashable tracked prop values force relayout for that turn.
236+ - On fallback, cached signature maps are cleared before continuing.
237+
238+ ### Measure cache design
239+
240+ - ` layout(...) ` accepts an optional shared measure cache: ` WeakMap<VNode, unknown> ` .
241+ - Cache identity key is the VNode object; lookups are then bucketed by ` (axis, maxW, maxH) ` .
242+ - Internally this is: ` VNode -> (row|column) -> maxW -> maxH -> LayoutResult<Size> ` .
243+ - Same VNode identity + same axis + same constraints hits; changing any of those misses.
244+ - Structurally equal but distinct VNode objects do not share entries.
245+ - On commit+layout turns, the renderer resets its shared WeakMap to avoid stale cross-identity reuse.
246+
247+ ### Performance characteristics
248+
249+ - Full layout computation is O(N) in visited nodes.
250+ - Signature comparison is O(N) when enabled.
251+ - When signatures are stable, the expensive ` layout(...) ` pass is skipped; the skip decision and reuse of the prior layout tree are O(1).
252+ - After a commit with skipped layout, damage-rect indexes are refreshed by walking runtime nodes.
253+
254+ ### Clarified invariants and edge cases
255+
256+ - The first signature pass against an empty previous map reports changed (bootstrap relayout).
257+ - Child add/remove/reorder in ` row ` /` column ` /` box ` is always detected as layout-relevant.
258+ - Style-only changes on ` text ` /` row ` /` box ` do not trigger relayout.
259+ - ` button ` ` id ` -only changes do not trigger relayout; label/padding changes do.
260+ - If any committed node is outside signature coverage, relayout is forced conservatively.
261+
217262## Borders
218263
219264` ui.box ` can draw a border around its content:
0 commit comments