From b42ed01e1c79713be141227763c5f2e2207a0b61 Mon Sep 17 00:00:00 2001 From: Payam Valadkhan Date: Sun, 23 Jul 2023 17:37:40 -0400 Subject: [PATCH] =?UTF-8?q?refactor(core):=20implement=20runtime=20=C9=B5?= =?UTF-8?q?=C9=B5getComponentDepsFactory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/src/render3/interfaces/definition.ts | 25 ++++++++++++---- .../core/src/render3/local_compilation.ts | 14 +++++---- packages/core/src/render3/scope.ts | 30 ++++++++++++++++--- 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/packages/core/src/render3/interfaces/definition.ts b/packages/core/src/render3/interfaces/definition.ts index 6d9719e916b29..d4cbc9c37e6a5 100644 --- a/packages/core/src/render3/interfaces/definition.ts +++ b/packages/core/src/render3/interfaces/definition.ts @@ -517,21 +517,34 @@ export type PipeTypeList = export const unusedValueExportToPlacateAjd = 1; /** - * NgModule scope info as provided by NgModule decorator. + * NgModule scope info as provided by AoT compiler + * + * In full compilation Ivy resolved all the "module with providers" and forward refs the whole array + * if at least one element if forward refed. So we end up with type `Type[]|(() => + * Type[])`. + * + * In local mode the compiler passes the raw info as they are to the runtimes as it is not possible + * to resolve them any further due to limited info at compile time. So we end up with type + * `RawScopeInfoFromDecorator[]`. */ export interface NgModuleScopeInfoFromDecorator { /** List of components, directives, and pipes declared by this module. */ - declarations?: Type[]|(() => Type[]); + declarations?: Type[]|(() => Type[])|RawScopeInfoFromDecorator[]; - /** List of modules or `ModuleWithProviders` imported by this module. */ - imports?: Type[]|(() => Type[]); + /** List of modules or standalone components imported by this module. */ + imports?: Type[]|(() => Type[])|RawScopeInfoFromDecorator[]; /** - * List of modules, `ModuleWithProviders`, components, directives, or pipes exported by this + * List of modules, components, directives, or pipes exported by this * module. */ - exports?: Type[]|(() => Type[]); + exports?: Type[]|(() => Type[])|RawScopeInfoFromDecorator[]; } +/** + * The array element type passed to: + * - NgModule's annotation imports/exports/declarations fields + * - standalone component annotation imports field + */ export type RawScopeInfoFromDecorator = Type|ModuleWithProviders|(() => Type)|(() => ModuleWithProviders); diff --git a/packages/core/src/render3/local_compilation.ts b/packages/core/src/render3/local_compilation.ts index 331bd5cd8e838..b94868aff6b3a 100644 --- a/packages/core/src/render3/local_compilation.ts +++ b/packages/core/src/render3/local_compilation.ts @@ -6,12 +6,14 @@ * found in the LICENSE file at https://angular.io/license */ -import {Type} from '../interface/type'; - -import {DependencyTypeList, RawScopeInfoFromDecorator} from './interfaces/definition'; +import {depsTracker} from './deps_tracker/deps_tracker'; +import {ComponentType, DependencyTypeList, RawScopeInfoFromDecorator} from './interfaces/definition'; export function ɵɵgetComponentDepsFactory( - type: Type, rawImports?: RawScopeInfoFromDecorator): () => DependencyTypeList { - // TODO(pmvald): Implement this runtime using deps tracker. - return () => []; + type: ComponentType, rawImports?: RawScopeInfoFromDecorator[]): () => DependencyTypeList { + return () => { + console.log('>>>>> ɵɵgetComponentDepsFactory factory called', type); + + return depsTracker.getComponentDependencies(type, rawImports).dependencies; + }; } diff --git a/packages/core/src/render3/scope.ts b/packages/core/src/render3/scope.ts index 3e38b73dd87f1..4ed7e29900203 100644 --- a/packages/core/src/render3/scope.ts +++ b/packages/core/src/render3/scope.ts @@ -6,12 +6,15 @@ * found in the LICENSE file at https://angular.io/license */ +import {isForwardRef, resolveForwardRef} from '../di/forward_ref'; import {Type} from '../interface/type'; import {noSideEffects} from '../util/closure'; import {EMPTY_ARRAY} from '../util/empty'; import {extractDefListOrFactory, getNgModuleDef} from './definition'; -import {ComponentDef, ComponentType, NgModuleScopeInfoFromDecorator} from './interfaces/definition'; +import {depsTracker} from './deps_tracker/deps_tracker'; +import {ComponentDef, ComponentType, NgModuleScopeInfoFromDecorator, RawScopeInfoFromDecorator} from './interfaces/definition'; +import {isModuleWithProviders} from './jit/util'; /** * Generated next to NgModules to monkey-patch directive and pipe references onto a component's @@ -43,8 +46,27 @@ export function ɵɵsetComponentScope( export function ɵɵsetNgModuleScope(type: any, scope: NgModuleScopeInfoFromDecorator): unknown { return noSideEffects(() => { const ngModuleDef = getNgModuleDef(type, true); - ngModuleDef.declarations = scope.declarations || EMPTY_ARRAY; - ngModuleDef.imports = scope.imports || EMPTY_ARRAY; - ngModuleDef.exports = scope.exports || EMPTY_ARRAY; + ngModuleDef.declarations = convertToTypeArray(scope.declarations || EMPTY_ARRAY); + ngModuleDef.imports = convertToTypeArray(scope.imports || EMPTY_ARRAY); + ngModuleDef.exports = convertToTypeArray(scope.exports || EMPTY_ARRAY); + + depsTracker.registerNgModule(type, scope); }); } + +function convertToTypeArray(values: Type[]|(() => Type[])| + RawScopeInfoFromDecorator[]): Type[]|(() => Type[]) { + if (typeof values === 'function') { + return values; + } + + if (values.some(isForwardRef)) { + return () => values.map(resolveForwardRef).map(maybeUnwrapModuleWithProviders); + } else { + return values.map(maybeUnwrapModuleWithProviders); + } +} + +function maybeUnwrapModuleWithProviders(value: any): Type { + return isModuleWithProviders(value) ? value.ngModule : value as Type; +}