fix(ivy): throw a better error when DI can't inject a ctor param (#33739)
Occasionally a factory function needs to be generated for an "invalid" constructor (one with parameters types which aren't injectable). Typically this happens in JIT mode where understanding of parameters cannot be done in the same "up-front" way that the AOT compiler can. This commit changes the JIT compiler to generate a new `invalidFactoryDep` call for each invalid parameter. This instruction will error at runtime if called, indicating both the index of the invalid parameter as well as (via the stack trace) the factory function which was generated for the type being constructed. Fixes #33637 PR Close #33739
This commit is contained in:

committed by
Andrew Kushnir

parent
7823c23932
commit
13c2fad240
@ -125,6 +125,11 @@ export enum R3ResolvedDependencyType {
|
||||
* Injecting the `ChangeDetectorRef` token. Needs special handling when injected into a pipe.
|
||||
*/
|
||||
ChangeDetectorRef = 2,
|
||||
|
||||
/**
|
||||
* An invalid dependency (no token could be determined). An error should be thrown at runtime.
|
||||
*/
|
||||
Invalid = 3,
|
||||
}
|
||||
|
||||
/**
|
||||
@ -271,11 +276,12 @@ export function compileFactoryFunction(meta: R3FactoryMetadata): R3FactoryFn {
|
||||
|
||||
function injectDependencies(
|
||||
deps: R3DependencyMetadata[], injectFn: o.ExternalReference, isPipe: boolean): o.Expression[] {
|
||||
return deps.map(dep => compileInjectDependency(dep, injectFn, isPipe));
|
||||
return deps.map((dep, index) => compileInjectDependency(dep, injectFn, isPipe, index));
|
||||
}
|
||||
|
||||
function compileInjectDependency(
|
||||
dep: R3DependencyMetadata, injectFn: o.ExternalReference, isPipe: boolean): o.Expression {
|
||||
dep: R3DependencyMetadata, injectFn: o.ExternalReference, isPipe: boolean,
|
||||
index: number): o.Expression {
|
||||
// Interpret the dependency according to its resolved type.
|
||||
switch (dep.resolved) {
|
||||
case R3ResolvedDependencyType.Token:
|
||||
@ -305,6 +311,8 @@ function compileInjectDependency(
|
||||
case R3ResolvedDependencyType.Attribute:
|
||||
// In the case of attributes, the attribute name in question is given as the token.
|
||||
return o.importExpr(R3.injectAttribute).callFn([dep.token]);
|
||||
case R3ResolvedDependencyType.Invalid:
|
||||
return o.importExpr(R3.invalidFactoryDep).callFn([o.literal(index)]);
|
||||
default:
|
||||
return unsupported(
|
||||
`Unknown R3ResolvedDependencyType: ${R3ResolvedDependencyType[dep.resolved]}`);
|
||||
|
@ -212,6 +212,7 @@ export class Identifiers {
|
||||
|
||||
static directiveInject: o.ExternalReference = {name: 'ɵɵdirectiveInject', moduleName: CORE};
|
||||
static invalidFactory: o.ExternalReference = {name: 'ɵɵinvalidFactory', moduleName: CORE};
|
||||
static invalidFactoryDep: o.ExternalReference = {name: 'ɵɵinvalidFactoryDep', moduleName: CORE};
|
||||
|
||||
static templateRefExtractor:
|
||||
o.ExternalReference = {name: 'ɵɵtemplateRefExtractor', moduleName: CORE};
|
||||
|
Reference in New Issue
Block a user