refactor: key FormAIController hints by field#9370
Conversation
Store per-field hint state in a WeakHashMap keyed by the field itself so hints become collectable once the field is unreferenced. The previous id-keyed HashMap kept entries reachable for the controller's lifetime, growing without bound across add/remove cycles. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
| * the form tree or application code, so a long-lived controller across many | ||
| * add/remove cycles does not accumulate stale hints. | ||
| */ | ||
| private final Map<HasValue<?, ?>, FormFieldHints> hintsByField = new WeakHashMap<>(); |
There was a problem hiding this comment.
I wonder if we should wrap the hints in a WeakReference. It seems likely that the value options lambdas will contain a reference to the component itself, which will prevent the entry from being garbage collected.
There was a problem hiding this comment.
The map entry is the only thing referencing the hints. If WeakReference was used, wouldn't the hints get GC'd unexpectedly?
| * the form tree or application code, so a long-lived controller across many | ||
| * add/remove cycles does not accumulate stale hints. | ||
| */ | ||
| private final Map<HasValue<?, ?>, FormFieldHints> hintsByField = new WeakHashMap<>(); |
There was a problem hiding this comment.
I wonder if there is a good way to move the id into the hints and drop the use of ComponentUtil.setData as mentioned in the issue description. Should we abandon that idea, what do you think?
There was a problem hiding this comment.
I did try this approach initially, here's the proto commit. But it requires adding package-private helper for testing purposes only, which isn't ideal. Keeping the String id attached to the field feels like the lesser evil.
EDIT: Well, maybe there could be a helper in the test package that just uses reflection. Should be fine



Summary
FormAIControllerpreviously stored hints inHashMap<String, FormFieldHints>keyed by an id. Nothing removed entries when fields left the form, so a long-lived controller across many add/remove cycles (dynamic forms, tabs, lists) grew the map without bound.WeakHashMap<HasValue<?, ?>, FormFieldHints>. When a field is removed from the form and unreferenced elsewhere, its hint entry becomes GC-eligible.Kapture.2026-05-26.at.12.55.54.mp4
Fixes https://github.com/orgs/vaadin/projects/103/views/3?pane=issue&itemId=189450046
🤖 Generated with Claude Code