a9a8c65a30
calculateLayoutWithContentGuards hides zero-content nodes (setDisplay DISPLAY_NONE, prior display recorded in `guarded`) inside its for(;;) loop, but only returns the restore closure on the normal path. If a later loop iteration's calculateLayout — or a measure func it invokes — throws after an earlier iteration already hid one or more nodes, the throw propagated before the closure was handed back, leaving those nodes DISPLAY_NONE on the live yoga tree. On the next commit applyZeroContentGuards short-circuits any already-DISPLAY_NONE node, so they were never un-hidden and the subtree stayed permanently invisible even after the offending input was removed. The callers wrap the RETURNED closure in try/finally, which cannot help because the closure was never returned. Wrap the loop so any exception restores everything currently in `guarded` (reverse order, same as the success closure) before re-throwing, leaving the live yoga tree clean. The original error propagates unchanged. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>