Frontmatter
| id | 8840 |
| title | VDOM Lifecycle: Fix Merge Race Condition and Async Destruction |
| state | Closed |
| labels | bugaicore |
| assignees | tobiu |
| createdAt | Jan 21, 2026, 12:15 AM |
| updatedAt | Jan 21, 2026, 12:17 AM |
| githubUrl | https://github.com/neomjs/neo/issues/8840 |
| author | tobiu |
| commentsCount | 1 |
| parentIssue | 8834 |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Jan 21, 2026, 12:17 AM |
VDOM Lifecycle: Fix Merge Race Condition and Async Destruction
tobiu added parent issue #8834 on Jan 21, 2026, 12:15 AM
tobiu assigned to @tobiu on Jan 21, 2026, 12:16 AM

tobiu
Jan 21, 2026, 12:16 AM
Input from Gemini 3 Pro:
✦ I have resolved the critical race conditions and test failures.
- Race Condition Fix (Snapshot Logic): Modified
executeVdomUpdateto snapshotmergedChildIdsduring payload collection. This ensures that late-arriving merges (which occur after collection but before resolution) are not cleared from the registry, forcing them to wait for the next update cycle instead of being silently dropped.- Async Destruction Fix: Updated
promiseUpdateto useregisterAsync, ensuring pending update promises are rejected if the component is destroyed.- Verification: All 248 unit tests (including
RaceConditionandAsyncDestruction) are passing.This ensures the stability of the new Teleportation/Hybrid architecture under high concurrency.
tobiu closed this issue on Jan 21, 2026, 12:17 AM
Objective
Fix critical race conditions in the VDOM update lifecycle that caused dropped updates and test timeouts.
Issues
executeCallbacks) would "acknowledge" the merge (and delete it from the registry) even though the payload was never generated.promiseUpdate()returned a new Promise that wasn't tied to the component's destruction lifecycle, causing indefinite hangs ifdestroy()was called while an update was pending.Fixes
VdomLifecycle.executeVdomUpdateto capture a snapshot ofmergedChildIdsduring the collection phase. This snapshot is passed toresolveVdomUpdate, ensuring we only acknowledge/clear merges that were actually processed. Late arrivals remain in the registry for the next cycle.promiseUpdateto useregisterAsync(Base.trap pattern), ensuring the promise rejects withNeo.isDestroyedif the component dies.Collision Filteringlogic.RaceCondition.spec.mjsandAsyncDestruction.spec.mjsto verify these fixes.