From 1f6249dae8414dedb62c0864008c06821c097be7 Mon Sep 17 00:00:00 2001 From: JoostK Date: Sun, 16 Jan 2022 18:20:01 +0100 Subject: [PATCH] refactor(compiler): remove directive matching from template compiler (#44731) The directive matching pass that happens during template compilation is redundant, since directive matching has already happened during the resolution phase of ngtsc and only matching declarables are provided to the template compiler. In JIT mode the declarables only become available after the primary template compilation has completed, so there is no need to perform directive matching in both JIT and AOT mode. PR Close #44731 --- .../compiler/src/render3/view/compiler.ts | 26 ++++------------ .../compiler/src/render3/view/template.ts | 30 +++---------------- 2 files changed, 10 insertions(+), 46 deletions(-) diff --git a/packages/compiler/src/render3/view/compiler.ts b/packages/compiler/src/render3/view/compiler.ts index 17f5e371809..791c67a9006 100644 --- a/packages/compiler/src/render3/view/compiler.ts +++ b/packages/compiler/src/render3/view/compiler.ts @@ -12,7 +12,7 @@ import * as core from '../../core'; import {AST, ParsedEvent, ParsedEventType, ParsedProperty} from '../../expression_parser/ast'; import * as o from '../../output/output_ast'; import {ParseError, ParseSourceSpan, sanitizeIdentifier} from '../../parse_util'; -import {CssSelector, SelectorMatcher} from '../../selector'; +import {CssSelector} from '../../selector'; import {ShadowCss} from '../../shadow_css'; import {BindingParser} from '../../template_parser/binding_parser'; import {error} from '../../util'; @@ -152,30 +152,16 @@ export function compileComponentFromMetadata( } } - // Generate the CSS matcher that recognize directive - let directiveMatcher: SelectorMatcher|null = null; - - if (meta.directives.length > 0) { - const matcher = new SelectorMatcher(); - for (const {selector, type} of meta.directives) { - matcher.addSelectables(CssSelector.parse(selector), type); - } - directiveMatcher = matcher; - } - // e.g. `template: function MyComponent_Template(_ctx, _cm) {...}` const templateTypeName = meta.name; const templateName = templateTypeName ? `${templateTypeName}_Template` : null; - const directivesUsed = new Set(); - const pipesUsed = new Set(); const changeDetection = meta.changeDetection; const template = meta.template; const templateBuilder = new TemplateDefinitionBuilder( constantPool, BindingScope.createRootScope(), 0, templateTypeName, null, null, templateName, - directiveMatcher, directivesUsed, meta.pipes, pipesUsed, R3.namespaceHTML, - meta.relativeContextFilePath, meta.i18nUseExternalIds); + R3.namespaceHTML, meta.relativeContextFilePath, meta.i18nUseExternalIds); const templateFunctionExpression = templateBuilder.buildTemplateFunction(template.nodes, []); @@ -210,15 +196,15 @@ export function compileComponentFromMetadata( definitionMap.set('template', templateFunctionExpression); // e.g. `directives: [MyDirective]` - if (directivesUsed.size) { - const directivesList = o.literalArr(Array.from(directivesUsed)); + if (meta.directives.length > 0) { + const directivesList = o.literalArr(meta.directives.map(dir => dir.type)); const directivesExpr = compileDeclarationList(directivesList, meta.declarationListEmitMode); definitionMap.set('directives', directivesExpr); } // e.g. `pipes: [MyPipe]` - if (pipesUsed.size) { - const pipesList = o.literalArr(Array.from(pipesUsed)); + if (meta.pipes.size > 0) { + const pipesList = o.literalArr(Array.from(meta.pipes.values())); const pipesExpr = compileDeclarationList(pipesList, meta.declarationListEmitMode); definitionMap.set('pipes', pipesExpr); } diff --git a/packages/compiler/src/render3/view/template.ts b/packages/compiler/src/render3/view/template.ts index 17a079c1a07..22bb3bd2439 100644 --- a/packages/compiler/src/render3/view/template.ts +++ b/packages/compiler/src/render3/view/template.ts @@ -24,7 +24,7 @@ import * as o from '../../output/output_ast'; import {ParseError, ParseSourceSpan, sanitizeIdentifier} from '../../parse_util'; import {DomElementSchemaRegistry} from '../../schema/dom_element_schema_registry'; import {isTrustedTypesSink} from '../../schema/trusted_types_sinks'; -import {CssSelector, SelectorMatcher} from '../../selector'; +import {CssSelector} from '../../selector'; import {BindingParser} from '../../template_parser/binding_parser'; import {error, partitionArray} from '../../util'; import * as t from '../r3_ast'; @@ -38,7 +38,7 @@ import {createLocalizeStatements} from './i18n/localize_utils'; import {I18nMetaVisitor} from './i18n/meta'; import {assembleBoundTextPlaceholders, assembleI18nBoundString, declareI18nVariable, getTranslationConstPrefix, hasI18nMeta, I18N_ICU_MAPPING_PREFIX, i18nFormatPlaceholderNames, icuFromI18nMessage, isI18nRootNode, isSingleI18nIcu, placeholdersToParams, TRANSLATION_VAR_PREFIX, wrapI18nPlaceholder} from './i18n/util'; import {StylingBuilder, StylingInstruction} from './styling_builder'; -import {asLiteral, chainedInstruction, CONTEXT_NAME, getAttrsForDirectiveMatching, getInterpolationArgsLength, IMPLICIT_REFERENCE, invalid, NON_BINDABLE_ATTR, REFERENCE_PREFIX, RENDER_FLAGS, RESTORED_VIEW_CONTEXT_NAME, trimTrailingNulls} from './util'; +import {asLiteral, chainedInstruction, CONTEXT_NAME, getInterpolationArgsLength, IMPLICIT_REFERENCE, invalid, NON_BINDABLE_ATTR, REFERENCE_PREFIX, RENDER_FLAGS, RESTORED_VIEW_CONTEXT_NAME, trimTrailingNulls} from './util'; @@ -200,8 +200,6 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver private constantPool: ConstantPool, parentBindingScope: BindingScope, private level = 0, private contextName: string|null, private i18nContext: I18nContext|null, private templateIndex: number|null, private templateName: string|null, - private directiveMatcher: SelectorMatcher|null, private directives: Set, - private pipeTypeByName: Map, private pipes: Set, private _namespace: o.ExternalReference, relativeContextFilePath: string, private i18nUseExternalIds: boolean, private _constants: ComponentDefConsts = createComponentDefConsts()) { @@ -215,10 +213,6 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver constantPool, () => this.allocateDataSlot(), (numSlots: number) => this.allocatePureFunctionSlots(numSlots), (name, localName, slot, value: o.Expression) => { - const pipeType = pipeTypeByName.get(name); - if (pipeType) { - this.pipes.add(pipeType); - } this._bindingScope.set(this.level, localName, value); this.creationInstruction(null, R3.pipe, [o.literal(slot), o.literal(name)]); }); @@ -638,9 +632,6 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver } } - // Match directives on non i18n attributes - this.matchDirectives(element.name, element); - // Regular element or ng-container creation mode const parameters: o.Expression[] = [o.literal(elementIndex)]; if (!isNgContainer) { @@ -891,9 +882,6 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver o.literal(tagNameWithoutNamespace), ]; - // find directives matching on a given node - this.matchDirectives(NG_TEMPLATE_TAG_NAME, template); - // prepare attributes parameter (including attributes used for directive matching) const attrsExprs: o.Expression[] = this.getAttributeExpressions( NG_TEMPLATE_TAG_NAME, template.attributes, template.inputs, template.outputs, @@ -910,9 +898,8 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver // Create the template function const templateVisitor = new TemplateDefinitionBuilder( this.constantPool, this._bindingScope, this.level + 1, contextName, this.i18n, - templateIndex, templateName, this.directiveMatcher, this.directives, this.pipeTypeByName, - this.pipes, this._namespace, this.fileBasedI18nSuffix, this.i18nUseExternalIds, - this._constants); + templateIndex, templateName, this._namespace, this.fileBasedI18nSuffix, + this.i18nUseExternalIds, this._constants); // Nested templates must not be visited until after their parent templates have completed // processing, so they are queued here until after the initial pass. Otherwise, we wouldn't @@ -1281,15 +1268,6 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver return args; } - private matchDirectives(elementName: string, elOrTpl: t.Element|t.Template) { - if (this.directiveMatcher) { - const selector = createCssSelector(elementName, getAttrsForDirectiveMatching(elOrTpl)); - this.directiveMatcher.match(selector, (cssSelector, staticType) => { - this.directives.add(staticType); - }); - } - } - /** * Prepares all attribute expression values for the `TAttributes` array. *