Repository navigation
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
A signal form field with any metadata rule, such as required(), min(), or debounce(), creates its own R3Injector, although only managed metadata keys use it. Removing a field that never had an injector also creates one just to destroy it. Add specs that count injector creation, plus a triage note with the root cause and fix options. The specs fail until a fix lands. The note is for review and isn't meant to be merged.
Flarette
force-pushed
the
triage/forms-injector-allocation
branch
from
October 26, 2026 07:06
20db882 to
ded228f
Compare
Member
|
Going to close the PRs as they're won't me merged as is. Let's move the discussions to the issues. |
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.
Issue #71623 | Triage note | Failing specs
Why the change
This adds failing specs showing that signal form fields create injectors that nothing uses, so that we can agree on the scope of the fix before I write it.
Special things to note
Injector.create, which ties them to the implementation. I couldn't find a public signal for "this field has an injector".FieldNodeStructure.destroy(), which the host teardown triage (Signal forms: destroying a form's component doesn't destroy its fields, so async validation keeps running #71622) also changes. Either can land first.Change outline
What this PR adds
Where the injector comes from
Injector.createcalls for a form over 50 array items, with one rule on each item, today:After the recommended fix:
Recommended fix: enter an injection context only for managed keys
// packages/forms/signals/src/field/metadata.ts, class FieldMetadataState runMetadataCreateLifecycle(): void { // ...early return and params-flag handling unchanged... - untracked(() => - runInInjectionContext(this.node.structure.injector, () => { - for (const key of this.node.logicNode.logic.getMetadataKeys()) { - if (key.create) { - /* create the managed value */ - } - } - }), - ); + untracked(() => { + for (const key of logic.getMetadataKeys()) { + if (!key.create) { + continue; + } + // Only managed keys need the field's injector, so it's created here and nowhere else. + runInInjectionContext(this.node.structure.injector, () => { + /* create the managed value, unchanged */ + }); + } + }); }// packages/forms/signals/src/field/structure.ts, class FieldNodeStructure destroy(): void { - this.injector.destroy(); + this._injector?.destroy(); }createstill runs in the field's injection context, which is all the guide promises. Plain keys only build acomputed().compatForm()children read the root's injector, and that read stays lazy.Alternatives
runMetadataCreateLifecycle()when no key hascreategetMetadata()adds keys lazily, so a cached flag could go staleR3InjectorDecisions for maintainers
Injector.createcalls acceptable in a regression test, or would you prefer another check?PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
Does this PR introduce a breaking change?