Skip to content

fix(forms): release removed Signal Forms array fields - #280

Merged
erkamyaman merged 1 commit into
mainfrom
fix/h-sigforms
Oct 11, 2026
Merged

erkamyaman merged 1 commit into
mainfrom
fix/h-sigforms

Conversation

@erkamyaman

@erkamyaman erkamyaman commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

What and why

On each push, wrapSignalSubmit walks structure.materializedChildren() and wraps every new field's submitState.selfSubmitting.set, pushing an undo closure onto entry.unwrap. That closure holds a reference to the field. The list was only emptied in unwrapSignalRoot, when the whole form root goes away.

With a real form(), removing an array item drops its field from materializedChildren(), 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.unwrap is now a Map from flag to undo function
  • each pass records the flags it reaches, then unwraps and deletes the ones it didn't, which releases removed fields and restores their original set
  • removing the whole form still unwraps everything

How it was verified

New test in forms-collector.test.ts with a real Signal Forms Tasks form. It adds and removes an array item 10 times with a push after each step, forces garbage collection, and checks with WeakRefs that the removed fields can be collected. On main all 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:check
  • pnpm typecheck (includes the ngc template checks)
  • pnpm test:devtools (all passing)
  • pnpm skills:check (when .claude/ changed): not changed
  • No docs change needed: the fix makes the code match existing docs (no-docs)
  • pnpm extension:build and extension/ui committed (when app/ changed): not changed
  • Checked in the browser with axe (when the UI changed): no UI change

Summary by CodeRabbit

  • Bug Fixes
    • DevTools no longer keeps removed fields from mounted Signal Forms in memory, allowing them to be reclaimed.
    • Forms continue to submit correctly after fields are added and removed.

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.
@erkamyaman erkamyaman added the no-docs This pull request needs no docs change (the reason is in the description) label Oct 11, 2026
@github-actions github-actions Bot added the area: package The ng-devtools package (packages/ng-devtools) label Oct 11, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Failed ❌

View logs ↗
73d7200 2026-10-11T03:14:19.916Z View logs ↗

@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 21042090-9870-4538-9691-d1cc99d5771e

📥 Commits

Reviewing files that changed from the base of the PR and between 58273c6 and 73d7200.


📒 Files selected for processing (2)
  • packages/devtools/src/__tests__/forms-collector.test.ts
  • packages/devtools/src/forms-collector.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review.



📝 Walkthrough

Walkthrough

The Signal Forms collector now tracks submit-wrapper restoration callbacks by flag and removes wrappers for flags absent from a later traversal. A new test removes array items, checks that their field nodes can be collected, and submits the mounted form.

Changes

Signal Forms wrapper cleanup

Layer / File(s) Summary
Track and restore submit wrappers
packages/devtools/src/forms-collector.ts, packages/devtools/src/__tests__/forms-collector.test.ts
The collector stores restoration callbacks by flag, restores wrappers for flags no longer reached, and clears callbacks when unwrapping a root. The test removes array items, checks their collection, and confirms the mounted form records a submit event.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix


Merge Risk | ⚪ Minimal · up to 73d72

Merge Risk: ⚪ Minimal · up to 73d72

The removed-field retention fix is covered by a mounted-form test, and no actionable issue remains before merge.

Security Architecture Review

Security architecture risk: ⚪ Minimal · up to 73d72

The change releases instrumentation for removed form fields while preserving the original submission setters. The apparent new public entrypoint is a test fixture, not an expanded production interface. No material security risk was identified in the reviewed change.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The changed behavior is confined to submit instrumentation on forms already discovered by the collector. The comparison adds neither a production caller nor greater submission authority; the new entrypoint-like declarations are test-only.

Trust Boundaries and Controls

  • inferred — Cleanup changes diagnostic ownership rather than validation or action authority. The wrapper preserves the original setter call, and Signal Forms submission continues through the existing form-root submission path.

Resilience and Maintainability Implications

  • inferred — Not reached is broader than removed: traversal limits and failed reads can cause a mounted flag to lose instrumentation until rediscovery. This can reduce diagnostic event continuity, including around pending submissions, but the cleanup restores rather than disables the application setter. No security-control dependency on those events was established in the inspected path.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: releasing removed Signal Forms array fields and fixing their retained references.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR


🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@erkamyaman
erkamyaman merged commit 43d7755 into main Oct 11, 2026
7 of 9 checks passed
@erkamyaman
erkamyaman deleted the fix/h-sigforms branch October 11, 2026 07:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: package The ng-devtools package (packages/ng-devtools) no-docs This pull request needs no docs change (the reason is in the description)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant