mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
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
This commit is contained in:
@@ -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<o.Expression>();
|
||||
const pipesUsed = new Set<o.Expression>();
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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<void>, 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<o.Expression>,
|
||||
private pipeTypeByName: Map<string, o.Expression>, private pipes: Set<o.Expression>,
|
||||
private _namespace: o.ExternalReference, relativeContextFilePath: string,
|
||||
private i18nUseExternalIds: boolean,
|
||||
private _constants: ComponentDefConsts = createComponentDefConsts()) {
|
||||
@@ -215,10 +213,6 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, 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<void>, 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<void>, LocalResolver
|
||||
o.literal(tagNameWithoutNamespace),
|
||||
];
|
||||
|
||||
// find directives matching on a given <ng-template> 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<void>, 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<void>, 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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user