f78121f6e7
The first exit() call now captures its value/error and initiates teardown synchronously; subsequent exit() calls are complete no-ops, so waitUntilExit resolves/rejects with the FIRST value rather than the last. This mirrors Ink's handleAppExit guard (isUnmounted || isUnmounting → early return). Previously each exit() queued a microtask that overwrote pendingExitResult/ pendingExitError before resolveExit ran, making it last-wins. An exitInitiated flag set at the top of exit() now guards the value capture and re-resolve, while the deferred microtask teardown (needed because exit() is called from inside the Vue update cycle) is preserved. Reverses the sweep-1 refutation: exit() was NOT already first-wins guarded. Also guard unmount-in-progress (isUnmounting parity) + value→error test. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>