angular/packages/core/src/render3/scope.ts
Payam Valadkhan 8798abb744 refactor(core): implement runtime logic to compute component dependencies in local compilation mode (#51377)
The runtime `ɵɵsetNgModuleScope` is modified to accept raw scope info as passed to it in local compilation mode. The runtime further registers the ng-module in the deps tracker. Then the runtime `ɵɵgetComponentDepsFactory` is implemented to use the deps tracker to get the component dependencies which leads to a valid and working Angular code.

PR Close #51377
2023-08-17 14:01:51 -07:00

72 lines
2.8 KiB
TypeScript

/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* 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 {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
* definition, when generating a direct reference in the component file would otherwise create an
* import cycle.
*
* See [this explanation](https://hackmd.io/Odw80D0pR6yfsOjg_7XCJg?view) for more details.
*
* @codeGenApi
*/
export function ɵɵsetComponentScope(
type: ComponentType<any>, directives: Type<any>[]|(() => Type<any>[]),
pipes: Type<any>[]|(() => Type<any>[])): void {
const def = type.ɵcmp as ComponentDef<any>;
def.directiveDefs = extractDefListOrFactory(directives, /* pipeDef */ false);
def.pipeDefs = extractDefListOrFactory(pipes, /* pipeDef */ true);
}
/**
* Adds the module metadata that is necessary to compute the module's transitive scope to an
* existing module definition.
*
* Scope metadata of modules is not used in production builds, so calls to this function can be
* marked pure to tree-shake it from the bundle, allowing for all referenced declarations
* to become eligible for tree-shaking as well.
*
* @codeGenApi
*/
export function ɵɵsetNgModuleScope(type: any, scope: NgModuleScopeInfoFromDecorator): unknown {
return noSideEffects(() => {
const ngModuleDef = getNgModuleDef(type, true);
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<any>[]|(() => Type<any>[])|
RawScopeInfoFromDecorator[]): Type<any>[]|(() => Type<any>[]) {
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<any> {
return isModuleWithProviders(value) ? value.ngModule : value as Type<any>;
}