Skip to content

perf: deferred Yoga layout-cache follow-ups (skip-clean-children, cached min-content, Reset dead-code) + cross-axis measure-cache staleness #681

Description

@azchohfi

Follow-up tracking for Yoga layout-engine work intentionally deferred from #658 / #670 (the layout-cache-guards + inline-per-node-arrays perf PR). Filing so the deferred items and one residual correctness gap surfaced by the pre-GO audit aren't lost. Scope: src/Reactor/Yoga/ only.

Deferred perf optimizations (each: why deferred / what it'd take)

Residual correctness gap surfaced by the pre-GO stale-state audit (please triage)

Flagged as correctness, not just perf — included here for traceability but may warrant its own priority/label.

Cross-axis measure-cache staleness after the #138 setter guards. The #138 equality guards + FlexPanel no longer re-dirtying every child each MeasureOverride correctly enable the layout cache, but they remove the implicit per-frame refresh that used to keep measure-backed leaves fresh. The #140 ComputeMinContent probe re-dirties a leaf only on a MAIN-axis min-content changeResolveMinDimension returns Undefined for the cross axis (no probe). So a content change that alters a flex child's cross-axis size (e.g. wrapping-text height when the longest word is unchanged), or the size of a flex-basis:0 / explicit-min child, without changing main-axis min-content, leaves the Yoga leaf clean → the input-keyed measurement cache (CachedLayout/CachedMeasurements) serves a stale size. Pre-#138, the accidental per-frame re-dirty masked this. Same risk class as the already-fixed ComputedFlexBasis regression (#670), but for the measure cache rather than the resolved basis.

Exposure: narrow but real and non-self-correcting — flex items with multi-line/wrapping text whose height changes from content updates, or content-driven cross-axis sizing under basis:0/explicit-min. Common single-line cases (grid cells, labels, numbers) stay correct because their main-axis min-content tracks the change.

Candidate fixes: (a) host/reconciler → YogaNode.MarkDirty bridge when measure-backed child content changes — the faithful Yoga contract; cross-cutting (Core/Reconciler + a FlexPanel notify API), preserves the perf win. (b) FlexPanel-local: re-measure each measure-leaf at its last-resolved constraint and compare, dirtying on change — fully correct but adds a measure/child/pass (perf-sensitive, wobble/LayoutCycleException care needed). (c) Probe both axes in ComputeMinContent — changes CSS cross-axis-min semantics, not acceptable as-is.

A repro selftest (mutate a wrapping-text flex child's content without touching its Yoga style; assert the panel height updates) would pin this; the fixture lives outside src/Reactor/Yoga/.

Refs: #658, #670. Exposed by the #138 setter-equality guards.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions