Summary
The {@for} loop syntax mandates a trackBy clause, which is a key part of our framework's "correct by default" philosophy. This syntax is parsed by the "Go Inspector" compiler, but the corresponding DOM reconciliation logic in the runtime does not yet use the provided key.
This issue tracks the work to implement a keyed diffing algorithm in our VDOM runtime. This is critical for enabling high-performance, predictable list rendering.
Problem
Without keyed reconciliation, the runtime can only diff lists of children by their index. This leads to two major problems:
- Poor Performance: When a list is re-sorted, or an item is added/removed from the beginning, an index-based diff will incorrectly assume every single item in the list has changed. This causes a cascade of unnecessary DOM updates (or worse, full teardown and rebuild) instead of a simple, surgical change.
- Incorrect Behavior: State held in child components (like
IsChecked in a checkbox) can be lost or "smeared" across the wrong components during a re-render, as the framework misidentifies which component is which.
Proposed Solution
We must upgrade the runtime's patch/diffing algorithm to perform a keyed reconciliation when diffing an element's children.
This algorithm, inspired by patterns in Blazor, React, and Angular, should generally follow these steps when comparing the old list of child VNodes to the new list:
- Create a map of the old
VNodes (or their corresponding DOM elements) indexed by their key.
- Iterate through the new list of
VNodes.
- For each
newVNode, check its key against the "old key map."
- Key Found (Update/Move): If the key exists, we know this is the same element. We patch this existing element with the new
VNode's properties and move it to the correct new index in the DOM. We then remove it from the "old key map."
- Key Not Found (Add): This is a new item. Create a new DOM element and insert it at the current index.
- Cleanup (Remove): After iterating through the new list, any
VNodes remaining in the "old key map" no longer exist in the new list. These elements must be unmounted and removed from the DOM.
Acceptance Criteria
Summary
The
{@for}loop syntax mandates atrackByclause, which is a key part of our framework's "correct by default" philosophy. This syntax is parsed by the "Go Inspector" compiler, but the corresponding DOM reconciliation logic in the runtime does not yet use the provided key.This issue tracks the work to implement a keyed diffing algorithm in our VDOM runtime. This is critical for enabling high-performance, predictable list rendering.
Problem
Without keyed reconciliation, the runtime can only diff lists of children by their index. This leads to two major problems:
IsCheckedin a checkbox) can be lost or "smeared" across the wrong components during a re-render, as the framework misidentifies which component is which.Proposed Solution
We must upgrade the runtime's patch/diffing algorithm to perform a keyed reconciliation when diffing an element's children.
This algorithm, inspired by patterns in Blazor, React, and Angular, should generally follow these steps when comparing the old list of child
VNodesto the new list:VNodes(or their corresponding DOM elements) indexed by their key.VNodes.newVNode, check its key against the "old key map."VNode's properties and move it to the correct new index in the DOM. We then remove it from the "old key map."VNodesremaining in the "old key map" no longer exist in the new list. These elements must be unmounted and removed from the DOM.Acceptance Criteria
keyprovided byVNodes.insertBefore), not the destruction and re-creation of all list elements.