Skip to content

refactor: key FormAIController hints by field#9370

Draft
tomivirkki wants to merge 1 commit into
mainfrom
refactor/key-by-field
Draft

refactor: key FormAIController hints by field#9370
tomivirkki wants to merge 1 commit into
mainfrom
refactor/key-by-field

Conversation

@tomivirkki
Copy link
Copy Markdown
Member

@tomivirkki tomivirkki commented May 26, 2026

Summary

  • FormAIController previously stored hints in HashMap<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.
  • Switched storage to 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

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>
@sonarqubecloud
Copy link
Copy Markdown

@tomivirkki tomivirkki requested a review from ugur-vaadin May 26, 2026 10:11
* 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<>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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<>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Member Author

@tomivirkki tomivirkki May 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@tomivirkki tomivirkki marked this pull request as draft May 27, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants