Revert "perf(compiler-cli): only emit directive/pipe references that are used (#38539)" (#38765)

This reverts commit 4faac78e32.
internal failure:
https://test.corp.google.com/ui#id=OCL:329948619:BASE:329967516:1599160428139:d63165ae

PR Close #38765
This commit is contained in:
Andrew Scott 2020-09-09 11:24:50 -07:00 committed by atscott
parent b0ca3cd0c4
commit 18f84a0328
1 changed files with 24 additions and 32 deletions

View File

@ -495,49 +495,36 @@ export class ComponentDecoratorHandler implements
// Set up the R3TargetBinder, as well as a 'directives' array and a 'pipes' map that are later
// fed to the TemplateDefinitionBuilder. First, a SelectorMatcher is constructed to match
// directives that are in scope.
type MatchedDirective = DirectiveMeta&{selector: string};
const matcher = new SelectorMatcher<MatchedDirective>();
const matcher = new SelectorMatcher<DirectiveMeta&{expression: Expression}>();
const directives: {selector: string, expression: Expression}[] = [];
for (const dir of scope.compilation.directives) {
if (dir.selector !== null) {
matcher.addSelectables(CssSelector.parse(dir.selector), dir as MatchedDirective);
const {ref, selector} = dir;
if (selector !== null) {
const expression = this.refEmitter.emit(ref, context);
directives.push({selector, expression});
matcher.addSelectables(CssSelector.parse(selector), {...dir, expression});
}
}
const pipes = new Map<string, Reference<ClassDeclaration>>();
const pipes = new Map<string, Expression>();
for (const pipe of scope.compilation.pipes) {
pipes.set(pipe.name, pipe.ref);
pipes.set(pipe.name, this.refEmitter.emit(pipe.ref, context));
}
// Next, the component template AST is bound using the R3TargetBinder. This produces a
// Next, the component template AST is bound using the R3TargetBinder. This produces an
// BoundTarget, which is similar to a ts.TypeChecker.
const binder = new R3TargetBinder(matcher);
const bound = binder.bind({template: metadata.template.nodes});
// The BoundTarget knows which directives and pipes matched the template.
const usedDirectives = bound.getUsedDirectives().map(directive => {
return {
selector: directive.selector,
expression: this.refEmitter.emit(directive.ref, context),
};
});
const usedPipes: {pipeName: string, expression: Expression}[] = [];
for (const pipeName of bound.getUsedPipes()) {
if (!pipes.has(pipeName)) {
continue;
}
const pipe = pipes.get(pipeName)!;
usedPipes.push({
pipeName,
expression: this.refEmitter.emit(pipe, context),
});
}
const usedDirectives = bound.getUsedDirectives();
const usedPipes = bound.getUsedPipes().map(name => pipes.get(name)!);
// Scan through the directives/pipes actually used in the template and check whether any
// import which needs to be generated would create a cycle.
const cycleDetected =
usedDirectives.some(dir => this._isCyclicImport(dir.expression, context)) ||
usedPipes.some(pipe => this._isCyclicImport(pipe.expression, context));
usedPipes.some(pipe => this._isCyclicImport(pipe, context));
if (!cycleDetected) {
// No cycle was detected. Record the imports that need to be created in the cycle detector
@ -545,8 +532,8 @@ export class ComponentDecoratorHandler implements
for (const {expression} of usedDirectives) {
this._recordSyntheticImport(expression, context);
}
for (const {expression} of usedPipes) {
this._recordSyntheticImport(expression, context);
for (const pipe of usedPipes) {
this._recordSyntheticImport(pipe, context);
}
// Check whether the directive/pipe arrays in ɵcmp need to be wrapped in closures.
@ -555,11 +542,16 @@ export class ComponentDecoratorHandler implements
const wrapDirectivesAndPipesInClosure =
usedDirectives.some(
dir => isExpressionForwardReference(dir.expression, node.name, context)) ||
usedPipes.some(
pipe => isExpressionForwardReference(pipe.expression, node.name, context));
usedPipes.some(pipe => isExpressionForwardReference(pipe, node.name, context));
data.directives = usedDirectives;
data.pipes = new Map(usedPipes.map(pipe => [pipe.pipeName, pipe.expression]));
// Actual compilation still uses the full scope, not the narrowed scope determined by
// R3TargetBinder. This is a hedge against potential issues with the R3TargetBinder - right
// now the TemplateDefinitionBuilder is the "source of truth" for which directives/pipes are
// actually used (though the two should agree perfectly).
//
// TODO(alxhub): switch TemplateDefinitionBuilder over to using R3TargetBinder directly.
data.directives = directives;
data.pipes = pipes;
data.wrapDirectivesAndPipesInClosure = wrapDirectivesAndPipesInClosure;
} else {
// Declaring the directiveDefs/pipeDefs arrays directly would require imports that would