Repository navigation
fix(forms): release removed Signal Forms array fields - #280
Merged
Merged
Conversation
The Signal Forms collector wraps each field's selfSubmitting flag and keeps an undo closure, which holds the field, until the whole form root leaves the page. Removing an array item drops its field from materializedChildren and adding one creates a new field, so a form whose array grows and shrinks kept every field it had ever seen. Each push now unwraps and forgets the flags it no longer reaches.
🚀 Deploying Preview to Cloudflare 🚀Preview Deployments by commit
|
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
On each push,
wrapSignalSubmitwalksstructure.materializedChildren()and wraps every new field'ssubmitState.selfSubmitting.set, pushing an undo closure ontoentry.unwrap. That closure holds a reference to the field. The list was only emptied inunwrapSignalRoot, when the whole form root goes away.With a real
form(), removing an array item drops its field frommaterializedChildren(), and adding an item creates a brand-new field. So any Signal Form with a dynamic array (todo lists, line items, "add another address") kept every field it ever rendered, along with that field's nested fields and signal graph, for as long as the form stayed on the page. On a long-lived page that grows without limit.The fix:
entry.unwrapis now aMapfrom flag to undo functionsetHow it was verified
New test in
forms-collector.test.tswith a real Signal FormsTasksform. It adds and removes an array item 10 times with a push after each step, forces garbage collection, and checks withWeakRefs that the removed fields can be collected. Onmainall of them are still alive. With the fix none of the checked ones are. All package tests pass.pnpm commit:check(commit messages follow the guidelines)pnpm format:checkpnpm typecheck(includes thengctemplate checks)pnpm test:devtools(all passing)pnpm skills:check(when.claude/changed): not changedno-docs)pnpm extension:buildandextension/uicommitted (whenapp/changed): not changedSummary by CodeRabbit