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
feat(compiler-cli): exclude abstract classes from `strictInjectionPar… #44615
base: main
Are you sure you want to change the base?
Conversation
72cc61c
to
7f30792
Compare
| expect(diags[0].code).toBe(ngErrorCode(ErrorCode.DIRECTIVE_INHERITS_UNDECORATED_CTOR)); | ||
| expect(diags[0].messageText) | ||
| .toEqual( | ||
| `The directive AbstractMiddleDir inherits its constructor from ParentClass, but the latter does not have an Angular decorator of its own. Dependency injection will not be able to resolve the parameters of ParentClass's constructor. Either add a @Directive decorator to ParentClass, or add an explicit constructor to AbstractMiddleDir.`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We used to report this report this error for abstract classes and I haven't changed this, but I'm wondering if we should exempt abstract directives from this error.
| @Injectable({ providedIn: 'root', useValue: null }) | ||
| export class UseValueService extends ParentService {} | ||
|
|
||
| @Injectable({ providedIn: 'root', useClass: ConcreteServiceWithCtor }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interestingly, we don't check useClass here like we check providers in the providers array!
efbc3f0
to
b1db475
Compare
b1db475
to
7be53d8
Compare
|
@JoostK It looks like this hasn't been updated in a while. Is this a PR we'd like to merge for 14? |
It's ready to go from my side, just awaiting review. I'm afraid we're short on time to get this LGTM'd in time. |
| const ctorDeps = getConstructorDependencies(declaration, this.host, this.isCore); | ||
| return { | ||
| ctorDeps: unwrapConstructorDependencies(ctorDeps), | ||
| }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this call registerInjectable before returning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm yeah that might make sense to avoid potential repeated work
reviewed-for: public-api
quick note: I would might classify this as a fix. I don't think the distinction will matter if it gets merged before the feature freeze for v14
7be53d8
to
a703061
Compare
|
This PR was merged into the repository by commit 9cf14ff. |
…ctionParameters` requirement (angular#44615)" This reverts commit 9cf14ff.
|
We have to roll this back due to breakage in g3. This will likely need forward fixes in order to land. |
…meters` requirement In AOT compilations, the `strictInjectionParameters` compiler option can be enabled to report errors when an `@Injectable` annotated class has a constructor with parameters that do not provide an injection token, e.g. only a primitive type or interface. Since Ivy it's become required that any class with Angular behavior (e.g. the `ngOnDestroy` lifecycle hook) is decorated using an Angular decorator, which meant that `@Injectable()` may need to have been added to abstract base classes. Doing so would then report an error if `strictInjectionParameters` is enabled, if the abstract class has an incompatible constructor for DI purposes. This may be fine though, as a subclass may call the constructor explicitly without relying on Angular's DI mechanism. Therefore, this commit excludes abstract classes from the `strictInjectionParameters` check. This avoids an error from being reported at compile time. If the constructor ends up being used by Angular's DI system at runtime, then the factory function of the abstract class will throw an error by means of the `ɵɵinvalidFactory` instruction. In addition to the runtime error, this commit also analyzes the inheritance chain of an injectable without a constructor to verify that their inherited constructor is valid. Closes angular#37914
a703061
to
b0ba89e
Compare


…ameters` requirement
In AOT compilations, the
strictInjectionParameterscompiler option canbe enabled to report errors when an
@Injectableannotated class has aconstructor with parameters that do not provide an injection token, e.g.
only a primitive type or interface.
Since Ivy it's become required that any class with Angular behavior
(e.g. the
ngOnDestroylifecycle hook) is decorated using an Angulardecorator, which meant that
@Injectable()may need to have been addedto abstract base classes. Doing so would then report an error if
strictInjectionParametersis enabled, if the abstract class has anincompatible constructor for DI purposes. This may be fine though, as
a subclass may call the constructor explicitly without relying on
Angular's DI mechanism.
Therefore, this commit excludes abstract classes from the
strictInjectionParameterscheck. This avoids an error from beingreported at compile time. If the constructor ends up being used by
Angular's DI system at runtime, then the factory function of the
abstract class will throw an error by means of the
ɵɵinvalidFactoryinstruction.
Closes #37914