From 7f7dc7c294bd85397a5cebbea22757cb89cc3943 Mon Sep 17 00:00:00 2001 From: Andrew Kushnir Date: Sun, 20 Oct 2019 22:14:34 -0700 Subject: [PATCH] perf(ivy): avoid unnecessary i18n pass while processing a template (#33284) Prior to this commit, we always invoked second i18n pass (in case whitespace removal is on, which is a default), even if a given template doesn't contain i18n information. Now we store a flag (that indicates presence of i18n information in a template) during first i18n pass and use it to check whether second pass is needed. PR Close #33284 --- .../compiler/src/render3/view/i18n/meta.ts | 5 +++++ .../compiler/src/render3/view/template.ts | 20 ++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/compiler/src/render3/view/i18n/meta.ts b/packages/compiler/src/render3/view/i18n/meta.ts index 3fed00ce11..2e10fe02f4 100644 --- a/packages/compiler/src/render3/view/i18n/meta.ts +++ b/packages/compiler/src/render3/view/i18n/meta.ts @@ -44,6 +44,9 @@ const setI18nRefs: VisitNodeFn = (htmlNode, i18nNode) => { * stored with other element's and attribute's information. */ export class I18nMetaVisitor implements html.Visitor { + // whether visited nodes contain i18n information + public hasI18nMeta: boolean = false; + // i18n message generation factory private _createI18nMessage = createI18nMessageFactory(this.interpolationConfig); @@ -63,6 +66,7 @@ export class I18nMetaVisitor implements html.Visitor { visitElement(element: html.Element): any { if (hasI18nAttrs(element)) { + this.hasI18nMeta = true; const attrs: html.Attribute[] = []; const attrsMeta: {[key: string]: string} = {}; @@ -111,6 +115,7 @@ export class I18nMetaVisitor implements html.Visitor { visitExpansion(expansion: html.Expansion, currentMessage: i18n.Message|undefined): any { let message; const meta = expansion.i18n; + this.hasI18nMeta = true; if (meta instanceof i18n.IcuPlaceholder) { // set ICU placeholder name (e.g. "ICU_1"), // generated while processing root element contents, diff --git a/packages/compiler/src/render3/view/template.ts b/packages/compiler/src/render3/view/template.ts index b06bd05b38..6d2e0d6c6a 100644 --- a/packages/compiler/src/render3/view/template.ts +++ b/packages/compiler/src/render3/view/template.ts @@ -1965,19 +1965,21 @@ export function parseTemplate( // before we run whitespace removal process, because existing i18n // extraction process (ng xi18n) relies on a raw content to generate // message ids - rootNodes = html.visitAll( - new I18nMetaVisitor(interpolationConfig, !preserveWhitespaces, i18nLegacyMessageIdFormat), - rootNodes); + const i18nMetaVisitor = new I18nMetaVisitor( + interpolationConfig, /* keepI18nAttrs */ !preserveWhitespaces, i18nLegacyMessageIdFormat); + rootNodes = html.visitAll(i18nMetaVisitor, rootNodes); if (!preserveWhitespaces) { rootNodes = html.visitAll(new WhitespaceVisitor(), rootNodes); - // run i18n meta visitor again in case we remove whitespaces, because - // that might affect generated i18n message content. During this pass - // i18n IDs generated at the first pass will be preserved, so we can mimic - // existing extraction process (ng xi18n) - rootNodes = html.visitAll( - new I18nMetaVisitor(interpolationConfig, /* keepI18nAttrs */ false), rootNodes); + // run i18n meta visitor again in case whitespaces are removed (because that might affect + // generated i18n message content) and first pass indicated that i18n content is present in a + // template. During this pass i18n IDs generated at the first pass will be preserved, so we can + // mimic existing extraction process (ng xi18n) + if (i18nMetaVisitor.hasI18nMeta) { + rootNodes = html.visitAll( + new I18nMetaVisitor(interpolationConfig, /* keepI18nAttrs */ false), rootNodes); + } } const {nodes, errors, styleUrls, styles} = htmlAstToRender3Ast(rootNodes, bindingParser);