LearnNewsExamplesServices
Frontmatter
id8465
titleInvestigate VDOM ID Collisions and Create Reproduction Test
stateClosed
labels
bugaitestingcore
assigneestobiu
createdAtJan 9, 2026, 2:31 PM
updatedAtJan 9, 2026, 2:50 PM
githubUrlhttps://github.com/neomjs/neo/issues/8465
authortobiu
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJan 9, 2026, 2:50 PM

Investigate VDOM ID Collisions and Create Reproduction Test

Closed v11.19.1 bugaitestingcore
tobiu
tobiu commented on Jan 9, 2026, 2:31 PM

Investigate the root cause of issue #8464 where components appeared to share VDOM IDs or cross-contaminate.

Suspicions:

  1. Prototype sharing of _vdom objects leading to shared IDs.
  2. Race condition in VDomUpdate manager.

Goal: Create a unit test test/playwright/unit/vdom/AutoId.spec.mjs that reproduces the issue or confirms the safety of the current implementation.

tobiu added the bug label on Jan 9, 2026, 2:32 PM
tobiu added the ai label on Jan 9, 2026, 2:32 PM
tobiu added the testing label on Jan 9, 2026, 2:32 PM
tobiu added the core label on Jan 9, 2026, 2:32 PM
tobiu referenced in commit 98552e9 - "fix: architectural resolution for VDOM ID collisions (#8465)" on Jan 9, 2026, 2:49 PM
tobiu assigned to @tobiu on Jan 9, 2026, 2:49 PM
tobiu
tobiu Jan 9, 2026, 2:49 PM

Input from Gemini 3 Pro:

✦ I have implemented an architectural resolution for VDOM ID collisions, which were the root cause of the "Zombie Update" artifacts observed in the Portal app.

Investigation Summary

The issue was traced to ComponentManager.wrapperNodes. This Map uses VDOM node IDs as keys to map back to component instances for components that use a wrapper node (e.g. Portal.view.news.blog.List). When multiple components with wrapper nodes were created, their auto-generated VDOM IDs (e.g. neo-vnode-1) would collide in the global Map, causing the framework to incorrectly resolve component references during tree flattening.

Resolution

Instead of relying on auto-generated IDs for wrapper nodes, the framework now automatically assigns a stable, unique ID derived from the component instance ID:

  • VdomLifecycle: Automatically assigns me.id + '__wrapper' to the root VDOM node if it is a wrapper node.
  • Component.Base: Synchronizes this stable ID in afterSetId to maintain consistency if the component ID changes.

Verification

  • Added a new unit test: test/playwright/unit/vdom/AutoId.spec.mjs. This test successfully reproduces the collision bug by forcing IdGenerator resets and verifies that the fix prevents the collision.
  • Reverted the manual onConstructed ID fixes in the Portal app, as they are no longer required.

The system is now robust against auto-generated VDOM ID collisions for wrapped components.

Commit: 98552e98e (#8465)

tobiu closed this issue on Jan 9, 2026, 2:50 PM
tobiu cross-referenced by #8464 on Jan 9, 2026, 2:50 PM
tobiu cross-referenced by #8468 on Jan 9, 2026, 3:02 PM