-
-
Notifications
You must be signed in to change notification settings - Fork 2k
fix(signals): only warn about memory leak when source injector is root #5079
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix(signals): only warn about memory leak when source injector is root #5079
Conversation
The rxMethod and signalMethod memory leak warning now only fires when the source injector is a root or platform injector. Previously, the warning fired any time a reactive input was passed outside an injection context, even when the source injector (e.g. a component injector) would properly handle cleanup. Uses duck-typed access to Angular's internal R3Injector.scopes property to detect root/platform injectors. Closes ngrx#4991 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
✅ Deploy Preview for ngrx-io ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Hey @david-shortman 👋 Thanks for raising these PRs. I'm glad to see your PRs again! I don't think we should show the warning only for root/platform injectors. In the following situation: @Injectable()
export class ParentService {
readonly parentMethod = rxMethod(...);
}
@Component({
template: `
@if (show()) { <child /> }
`,
providers: [ParentService],
})
export class ParentComponent {
readonly show = signal(false);
}
@Component({ /* ... */ })
export class ChildComponent implements OnInit {
readonly parentService = inject(ParentService);
ngOnInit() {
this.parentService.parentMethod(interval(2_000));
}
}The memory leak will happen when Another problem with this implementation is using the private |
|
I'll see if I can detect this situation. Additionally, I can add testing that would catch a breaking change from Angular. Glad to be looking at NgRx again. I was curious to look at older issues I had been involved with but with the fresh lens of researching and validating ideas with Claude Code. |
|
👋 Hey all. If we’re looking to make changes here, I’d actually propose going into the opposite direction: show a deprecation message instead of a warning. In that sense, rxMethod would align much better with the other Angular signal-based functions like effect, linkedSignal, and the resource APIs. |
You're referring to requiring supplying the injection context explicitly Although I like the stylishness of the context being implicitly loaded, and the slightly less boilerplate that comes with it, I would support either direction. So you're saying that, like the other Angular signal functions, unless you call in an injection context like the constructor, then you must explicitly supply the intended injection context? |
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
rxMethodandsignalMethodwarn about a potential memory leak whenever a reactive input (signal, observable, or computation function) is passed outside an injection context — even when the source injector (captured at creation time) will properly handle cleanup. This produces false-positive warnings in common patterns such as:The warning is also inconsistent: it fires for scenario 2 (matrix below; component method call) but not scenario 4 (root service constructor call), even though scenario 4 is the one with actual leak potential.
Closes #4991
What is the new behavior?
The memory leak warning now only fires when all three conditions are met:
This correctly suppresses the warning when
rxMethod/signalMethodis initialized in a non-root injector (component or scoped service), since the source injector's lifecycle will handle cleanup.The detection uses duck-typed access to Angular's internal
R3Injector.scopesproperty. This is documented in code as an internal Angular API that may change in future versions.Scenario matrix
Does this PR introduce a breaking change?
Other information
isRootInjectorhelper usesR3Injector.scopes(Angular internal) via duck typing to avoid importingɵR3Injector. This is intentionally documented as relying on an internal API.rxMethod(in@ngrx/signals/rxjs-interop) andsignalMethod(in@ngrx/signals) were updated with the same fix.