Frontmatter
| id | 8874 |
| title | Investigate addVnodeComponentReferences Data Loss & TreeBuilder Symmetry |
| state | Open |
| labels | discussionaitestingcore |
| assignees | [] |
| createdAt | Jan 24, 2026, 12:30 AM |
| updatedAt | Jan 24, 2026, 12:40 AM |
| githubUrl | https://github.com/neomjs/neo/issues/8874 |
| author | tobiu |
| commentsCount | 3 |
| parentIssue | null |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
Investigate addVnodeComponentReferences Data Loss & TreeBuilder Symmetry

Input from Gemini 3 Pro:
✦ Refinement based on Architectural Intent:
The user clarified the intended architecture:
vdomcontains lightweight references (componentId + id).addVnodeComponentReferences()is intended to flatten VNode trees into this exact same shape.TreeBuilderis then expected to expand both (if needed) in an identical way.Investigation Pivot: The "Attribute Mismatch" theory might be incorrect if
vdomreferences are indeed naked. The investigation should focus on:
- Verifying that
vdomreferences andaddVnodeComponentReferencesoutputs are indeed structurally identical.- Checking if
TreeBuilderrespects this symmetry under alldepthconditions.- Understanding why the "Extra Delta" occurred in #8868 when we enforced this flattening (via
syncVnodeTree). It implies that for that specific test case, the "Flattened" state produced a different result than the "Full" state, which shouldn't happen if the pruning logic is perfect.This ticket should verify the "Happy Path" symmetry and identify why it drifted in the regression case.

Input from Gemini 3 Pro:
✦ Final Architecture Confirmation:
The user provided further evidence from
Container.Base.insert, which also usescreateVdomReference(). This confirms that the VDOM protocol is strictly:
- Containers/Parents hold References (
{componentId}) to their children.- Components hold their own Full VDOM (
_vdom).- TreeBuilder is the bridge that expands References into Full Trees for the Worker.
- addVnodeComponentReferences is the inverse bridge, flattening Worker Full Trees back into References for the App.
Conclusion for Investigation: The "Data Loss" hypothesis is definitely incorrect because the "Lost Data" (attributes on placeholders) should not exist in the VDOM reference model. The investigation in this ticket must focus on why the Transition (from Full to Flattened) triggered a reaction in
Helperin the specific regression case. It impliesHelperorTreeBuilderhandled the "Flattened" structure differently than the "Full" structure in a way that produced a delta, despite them being logically equivalent after expansion.This ticket is now purely about verifying and hardening this Symmetry.

Input from Gemini 3 Pro:
✦ Insights from Documentation (v10 Deep Dive & Asymmetric Updates):
Architectural Intent: The documentation explicitly states that a container's
vdomproperty "just lists its children" (references), andTreeBuilderis responsible for "intelligently expanding" them. This confirms thatsyncVnodeTree's role in flattening the structure (viaaddVnodeComponentReferences) is architecturally correct: it resets the component's state to the "Reference Model" after a "Full Model" update from the worker.The "Extra Delta" Mystery: Since
TreeBuilderexpands references into full structures before sending toHelper, the "Flattened" state (in App Worker) and "Full" state (in VDom Worker) should theoretically produce identical expanded outputs forHelperto compare. The fact that they don't (causing the regression) suggests thataddVnodeComponentReferencesmight be lossy in a way thatTreeBuildercannot recover from.Hypothesis:
addVnodeComponentReferencesmight be stripping Wrapper Nodes or specific structural metadata thatTreeBuilderrelies on to reconstruct the full tree correctly. IfTreeBuilderexpands a "Naked Reference" differently than a "Reference with Wrapper Metadata",Helperwill see a mismatch.Action Item: Investigate if
addVnodeComponentReferencescorrectly handles wrapped components and preserves necessary metadata forTreeBuilder.
Context:
ComponentManager.addVnodeComponentReferencesflattens a Full VNode tree into References. It creates references as{componentId, id}. Crucially, it discards all other properties (style,cls, etc.) from the node.Problem: When
syncVnodeTreeapplies this flattening to a component (e.g.Child),Child._vnodebecomes a "naked" reference. In the next update,TreeBuildergenerates a "rich" reference fromvdom(containingstyle, etc.).Helpercompares "Naked Old Reference" vs "Rich New Reference". Result: Attribute Mismatch -> Unnecessary Deltas.Baseline Behavior: In the baseline,
syncVnodeTreeoften skipped children (due togetChildIdsfiltering placeholders).Child._vnoderemained Full.Helpercompares "Rich New Reference" vs "Full Old Node". It seemsHelperhandles this "Pruning" case gracefully (ignoring the Full content).Goal:
Helper's behavior for Reference vs Full (Pruning logic).addVnodeComponentReferencesSHOULD preserve attributes (creating "Rich References").syncVnodeTreecould safely flatten trees without causing diffs._vnodestate more consistently with the "Placeholder" concept.Tasks:
Helper.addVnodeComponentReferencespreserving attributes.syncVnodeTreelogic.This explains the "Extra Delta" regression encountered in #8868.