diff --git a/packages/devtools/src/__tests__/forms-collector.test.ts b/packages/devtools/src/__tests__/forms-collector.test.ts
index 5f4e32d8..ac6f1931 100644
--- a/packages/devtools/src/__tests__/forms-collector.test.ts
+++ b/packages/devtools/src/__tests__/forms-collector.test.ts
@@ -11,6 +11,8 @@ import {
required,
} from '@angular/forms/signals';
import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
+import { setFlagsFromString } from 'node:v8';
+import { runInNewContext } from 'node:vm';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { attachForms, setupErrorOf } from '../forms-collector.ts';
import type { FormEvent } from '../forms.ts';
@@ -62,6 +64,18 @@ Component({
template: `
`,
})(SignUp);
+class Tasks {
+ model = signal({ name: '', items: [{ n: -1 }] });
+ form = form(this.model, (p) => required(p.name), {
+ submission: { action: async () => undefined },
+ });
+}
+Component({
+ selector: 'tasks-form',
+ imports: [FormField, FormRoot],
+ template: ``,
+})(Tasks);
+
function harness(maxEvents?: number) {
const calls: { name: string; args: any[] }[] = [];
const handlers = new Map unknown>();
@@ -182,6 +196,35 @@ describe('forms collector', () => {
expect(model.update).toBe(original.update);
});
+ it('lets array fields be collected once they are removed, while the form stays', async () => {
+ setFlagsFromString('--expose-gc');
+ const gc = runInNewContext('gc') as () => void;
+ const fixture = await mount(Tasks);
+ const { model, form: tree } = fixture.componentInstance as any;
+ const h = harness();
+ const refs: WeakRef