( container: Type<unknown> | AbstractType<unknown> | InjectorTypeWithProviders<unknown>, visitor: WalkProviderTreeVisitor, parents: (Type<unknown> | AbstractType<unknown>)[], dedup: Set<Type<unknown> | AbstractType<unknown>>, )
| 230 | * an injector definition are processed. (following View Engine semantics: see FW-1349) |
| 231 | */ |
| 232 | export function walkProviderTree( |
| 233 | container: Type<unknown> | AbstractType<unknown> | InjectorTypeWithProviders<unknown>, |
| 234 | visitor: WalkProviderTreeVisitor, |
| 235 | parents: (Type<unknown> | AbstractType<unknown>)[], |
| 236 | dedup: Set<Type<unknown> | AbstractType<unknown>>, |
| 237 | ): container is InjectorTypeWithProviders<unknown> { |
| 238 | container = resolveForwardRef(container); |
| 239 | if (!container) return false; |
| 240 | |
| 241 | // The actual type which had the definition. Usually `container`, but may be an unwrapped type |
| 242 | // from `InjectorTypeWithProviders`. |
| 243 | let defType: Type<unknown> | null = null; |
| 244 | |
| 245 | let injDef = getInjectorDef(container); |
| 246 | const cmpDef = !injDef && getComponentDef(container); |
| 247 | if (!injDef && !cmpDef) { |
| 248 | // `container` is not an injector type or a component type. It might be: |
| 249 | // * An `InjectorTypeWithProviders` that wraps an injector type. |
| 250 | // * A standalone directive or pipe that got pulled in from a standalone component's |
| 251 | // dependencies. |
| 252 | // Try to unwrap it as an `InjectorTypeWithProviders` first. |
| 253 | const ngModule: Type<unknown> | undefined = (container as InjectorTypeWithProviders<any>) |
| 254 | .ngModule as Type<unknown> | undefined; |
| 255 | injDef = getInjectorDef(ngModule); |
| 256 | if (injDef) { |
| 257 | defType = ngModule!; |
| 258 | } else { |
| 259 | // Not a component or injector type, so ignore it. |
| 260 | return false; |
| 261 | } |
| 262 | } else if (cmpDef && !cmpDef.standalone) { |
| 263 | return false; |
| 264 | } else { |
| 265 | defType = container as Type<unknown>; |
| 266 | } |
| 267 | |
| 268 | // Check for circular dependencies. |
| 269 | if (ngDevMode && parents.indexOf(defType) !== -1) { |
| 270 | const defName = stringify(defType); |
| 271 | const path = parents.map(stringify).concat(defName); |
| 272 | throw cyclicDependencyErrorWithDetails(defName, path); |
| 273 | } |
| 274 | |
| 275 | // Check for multiple imports of the same module |
| 276 | const isDuplicate = dedup.has(defType); |
| 277 | |
| 278 | if (cmpDef) { |
| 279 | if (isDuplicate) { |
| 280 | // This component definition has already been processed. |
| 281 | return false; |
| 282 | } |
| 283 | dedup.add(defType); |
| 284 | |
| 285 | if (cmpDef.dependencies) { |
| 286 | const deps = |
| 287 | typeof cmpDef.dependencies === 'function' ? cmpDef.dependencies() : cmpDef.dependencies; |
| 288 | for (const dep of deps) { |
| 289 | walkProviderTree(dep, visitor, parents, dedup); |
no test coverage detected
searching dependent graphs…