feat(ivy): compile @Injectable on classes not meant for DI (#28523)
In the past, @Injectable had no side effects and existing Angular code is therefore littered with @Injectable usage on classes which are not intended to be injected. A common example is: @Injectable() class Foo { constructor(private notInjectable: string) {} } and somewhere else: providers: [{provide: Foo, useFactory: ...}) Here, there is no need for Foo to be injectable - indeed, it's impossible for the DI system to create an instance of it, as it has a non-injectable constructor. The provider configures a factory for the DI system to be able to create instances of Foo. Adding @Injectable in Ivy signifies that the class's own constructor, and not a provider, determines how the class will be created. This commit adds logic to compile classes which are marked with @Injectable but are otherwise not injectable, and create an ngInjectableDef field with a factory function that throws an error. This way, existing code in the wild continues to compile, but if someone attempts to use the injectable it will fail with a useful error message. In the case where strictInjectionParameters is set to true, a compile-time error is thrown instead of the runtime error, as ngtsc has enough information to determine when injection couldn't possibly be valid. PR Close #28523
This commit is contained in:

committed by
Misko Hevery

parent
f8b67712bc
commit
d2742cf473
@ -340,7 +340,8 @@ export class NgtscProgram implements api.Program {
|
||||
this.rootDirs, this.options.preserveWhitespaces || false,
|
||||
this.options.i18nUseExternalIds !== false, this.moduleResolver, this.cycleAnalyzer),
|
||||
new DirectiveDecoratorHandler(this.reflector, evaluator, scopeRegistry, this.isCore),
|
||||
new InjectableDecoratorHandler(this.reflector, this.isCore),
|
||||
new InjectableDecoratorHandler(
|
||||
this.reflector, this.isCore, this.options.strictInjectionParameters || false),
|
||||
new NgModuleDecoratorHandler(
|
||||
this.reflector, evaluator, scopeRegistry, referencesRegistry, this.isCore,
|
||||
this.routeAnalyzer),
|
||||
|
Reference in New Issue
Block a user