(meta: R3FactoryMetadata)
| 104 | * Construct a factory function expression for the given `R3FactoryMetadata`. |
| 105 | */ |
| 106 | export function compileFactoryFunction(meta: R3FactoryMetadata): R3CompiledExpression { |
| 107 | const t = o.variable('__ngFactoryType__'); |
| 108 | let baseFactoryVar: o.ReadVarExpr | null = null; |
| 109 | |
| 110 | // The type to instantiate via constructor invocation. If there is no delegated factory, meaning |
| 111 | // this type is always created by constructor invocation, then this is the type-to-create |
| 112 | // parameter provided by the user (t) if specified, or the current type if not. If there is a |
| 113 | // delegated factory (which is used to create the current type) then this is only the type-to- |
| 114 | // create parameter (t). |
| 115 | const typeForCtor = !isDelegatedFactoryMetadata(meta) |
| 116 | ? new o.BinaryOperatorExpr(o.BinaryOperator.Or, t, meta.type.value) |
| 117 | : t; |
| 118 | |
| 119 | let ctorExpr: o.Expression | null = null; |
| 120 | |
| 121 | // If the factory has invalid dependencies (e.g. trying to inject an interface), we normally mark |
| 122 | // the `deps` as invalid so we can emit an invalid factory. In some environments we may not |
| 123 | // be able to determine if the dependency is invalid, because that depends on information in |
| 124 | // other files. To ensure that cases like that still compile, we need to add a `@ts-ignore` |
| 125 | // comment which allows the code to compile and then error at runtime. Note that it's important |
| 126 | // to put the comment on a statement, because it includes a new line which may break `return` |
| 127 | // statements if the comment is set on the expression. |
| 128 | const factoryComments = |
| 129 | meta.deps !== null && meta.deps !== 'invalid' && meta.deps.length > 0 |
| 130 | ? [tsIgnoreComment()] |
| 131 | : undefined; |
| 132 | |
| 133 | if (meta.deps !== null) { |
| 134 | // There is a constructor (either explicitly or implicitly defined). |
| 135 | if (meta.deps !== 'invalid') { |
| 136 | ctorExpr = new o.InstantiateExpr(typeForCtor, injectDependencies(meta.deps, meta.target)); |
| 137 | } |
| 138 | } else { |
| 139 | // There is no constructor, use the base class' factory to construct typeForCtor. |
| 140 | baseFactoryVar = o.variable(`ɵ${meta.name}_BaseFactory`); |
| 141 | ctorExpr = baseFactoryVar.callFn([typeForCtor]); |
| 142 | } |
| 143 | |
| 144 | const body: o.Statement[] = []; |
| 145 | let retExpr: o.Expression | null = null; |
| 146 | |
| 147 | function makeConditionalFactory(nonCtorExpr: o.Expression): o.ReadVarExpr { |
| 148 | const r = o.variable('__ngConditionalFactory__'); |
| 149 | body.push(new o.DeclareVarStmt(r.name, o.NULL_EXPR, o.DYNAMIC_TYPE)); |
| 150 | const ctorStmt = |
| 151 | ctorExpr !== null |
| 152 | ? r.set(ctorExpr).toStmt(factoryComments) |
| 153 | : o.importExpr(R3.invalidFactory).callFn([]).toStmt(); |
| 154 | // Always add a `ts-ignore` on the alternate factory. |
| 155 | body.push(o.ifStmt(t, [ctorStmt], [r.set(nonCtorExpr).toStmt([tsIgnoreComment()])])); |
| 156 | return r; |
| 157 | } |
| 158 | |
| 159 | if (isDelegatedFactoryMetadata(meta)) { |
| 160 | // This type is created with a delegated factory. If a type parameter is not specified, call |
| 161 | // the factory instead. |
| 162 | const delegateArgs = injectDependencies(meta.delegateDeps, meta.target); |
| 163 | // Either call `new delegate(...)` or `delegate(...)` depending on meta.delegateType. |
no test coverage detected
searching dependent graphs…