From e79fc02a2a164183fbba65dd7e5496239f74a8a2 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Wed, 20 Sep 2023 09:16:03 -0700 Subject: [PATCH] refactor(compiler): Allow collapsing i18n start/end ops that contain a pipe (#51876) Moves the empty element phase earlier, to before pipe creation. This ensures that adjacent i18nStart/i18nEnd ops will be collapsed into a isingle i18n op, rather than remaining uncollapsed if a pipe is inserted between them. PR Close #51876 --- packages/compiler/src/template/pipeline/src/emit.ts | 4 ++-- packages/compiler/src/template/pipeline/src/instruction.ts | 4 ++-- .../template/pipeline/src/phases/i18n_const_collection.ts | 5 +++-- .../template/pipeline/src/phases/i18n_message_extraction.ts | 5 +++-- .../src/template/pipeline/src/phases/ng_container.ts | 6 ++++++ packages/compiler/src/template/pipeline/src/phases/reify.ts | 2 +- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/packages/compiler/src/template/pipeline/src/emit.ts b/packages/compiler/src/template/pipeline/src/emit.ts index 823cb26f27a..58d1bdf7831 100644 --- a/packages/compiler/src/template/pipeline/src/emit.ts +++ b/packages/compiler/src/template/pipeline/src/emit.ts @@ -80,10 +80,11 @@ const phases: Phase[] = [ {kind: Kind.Tmpl, fn: phaseRemoveEmptyBindings}, {kind: Kind.Tmpl, fn: phaseConditionals}, {kind: Kind.Tmpl, fn: phaseNoListenersOnTemplates}, + {kind: Kind.Tmpl, fn: phaseGenerateProjectionDef}, + {kind: Kind.Tmpl, fn: phaseEmptyElements}, {kind: Kind.Tmpl, fn: phasePipeCreation}, {kind: Kind.Tmpl, fn: phasePipeVariadic}, {kind: Kind.Both, fn: phasePureLiteralStructures}, - {kind: Kind.Tmpl, fn: phaseGenerateProjectionDef}, {kind: Kind.Tmpl, fn: phaseGenerateVariables}, {kind: Kind.Tmpl, fn: phaseSaveRestoreView}, {kind: Kind.Tmpl, fn: phaseFindAnyCasts}, @@ -106,7 +107,6 @@ const phases: Phase[] = [ {kind: Kind.Both, fn: phaseNaming}, {kind: Kind.Tmpl, fn: phaseMergeNextContext}, {kind: Kind.Tmpl, fn: phaseNgContainer}, - {kind: Kind.Tmpl, fn: phaseEmptyElements}, {kind: Kind.Tmpl, fn: phaseNonbindable}, {kind: Kind.Both, fn: phasePureFunctionExtraction}, {kind: Kind.Tmpl, fn: phaseAlignPipeVariadicVarOffset}, diff --git a/packages/compiler/src/template/pipeline/src/instruction.ts b/packages/compiler/src/template/pipeline/src/instruction.ts index ad5303a1311..fd30cec0096 100644 --- a/packages/compiler/src/template/pipeline/src/instruction.ts +++ b/packages/compiler/src/template/pipeline/src/instruction.ts @@ -203,8 +203,8 @@ export function i18nStart(slot: number, constIndex: number): ir.CreateOp { return call(Identifiers.i18nStart, [o.literal(slot), o.literal(constIndex)], null); } -export function i18n(slot: number): ir.CreateOp { - return call(Identifiers.i18n, [o.literal(slot)], null); +export function i18n(slot: number, constIndex: number): ir.CreateOp { + return call(Identifiers.i18n, [o.literal(slot), o.literal(constIndex)], null); } export function i18nEnd(): ir.CreateOp { diff --git a/packages/compiler/src/template/pipeline/src/phases/i18n_const_collection.ts b/packages/compiler/src/template/pipeline/src/phases/i18n_const_collection.ts index e1c30bb6d81..644636110fe 100644 --- a/packages/compiler/src/template/pipeline/src/phases/i18n_const_collection.ts +++ b/packages/compiler/src/template/pipeline/src/phases/i18n_const_collection.ts @@ -7,7 +7,7 @@ */ import * as ir from '../../ir'; -import {type CompilationJob, ComponentCompilationJob} from '../compilation'; +import {ComponentCompilationJob} from '../compilation'; /** * Lifts i18n properties into the consts array. @@ -28,7 +28,8 @@ export function phaseI18nConstCollection(job: ComponentCompilationJob): void { // Assign const index to i18n ops that messages were extracted from. for (const unit of job.units) { for (const op of unit.create) { - if (op.kind === ir.OpKind.I18nStart && messageConstIndices[op.xref] !== undefined) { + if ((op.kind === ir.OpKind.I18nStart || op.kind === ir.OpKind.I18n) && + messageConstIndices[op.xref] !== undefined) { op.messageIndex = messageConstIndices[op.xref]; } } diff --git a/packages/compiler/src/template/pipeline/src/phases/i18n_message_extraction.ts b/packages/compiler/src/template/pipeline/src/phases/i18n_message_extraction.ts index 0ce1ddfb2a6..871d802ecba 100644 --- a/packages/compiler/src/template/pipeline/src/phases/i18n_message_extraction.ts +++ b/packages/compiler/src/template/pipeline/src/phases/i18n_message_extraction.ts @@ -33,7 +33,8 @@ export function phaseI18nMessageExtraction(job: ComponentCompilationJob): void { job.relativeContextFilePath.replace(/[^A-Za-z0-9]/g, '_').toUpperCase() + '_'; for (const unit of job.units) { for (const op of unit.create) { - if (op.kind === ir.OpKind.I18nStart && op.i18n instanceof i18n.Message) { + if ((op.kind === ir.OpKind.I18nStart || op.kind === ir.OpKind.I18n) && + op.i18n instanceof i18n.Message) { // Sort the params map to match the ordering in TemplateDefinitionBuilder. const params = Object.fromEntries(Object.entries(getParams(op)).sort()); @@ -134,7 +135,7 @@ function i18nGenerateClosureVar( /** * Gets the placeholder values for an i18n block. */ -function getParams(op: ir.I18nStartOp): {[placeholder: string]: o.Expression} { +function getParams(op: ir.I18nStartOp|ir.I18nOp): {[placeholder: string]: o.Expression} { const params = op.tagNameParams; for (const placeholder in (op.i18n as i18n.Message).placeholders) { if (params[placeholder] === undefined) { diff --git a/packages/compiler/src/template/pipeline/src/phases/ng_container.ts b/packages/compiler/src/template/pipeline/src/phases/ng_container.ts index 179ebe8adae..bc744edf05f 100644 --- a/packages/compiler/src/template/pipeline/src/phases/ng_container.ts +++ b/packages/compiler/src/template/pipeline/src/phases/ng_container.ts @@ -18,6 +18,12 @@ export function phaseNgContainer(job: CompilationJob): void { for (const unit of job.units) { const updatedElementXrefs = new Set(); for (const op of unit.create) { + if (op.kind === ir.OpKind.Element && op.tag === CONTAINER_TAG) { + // Transmute the `Element` instruction to `Container`. + (op as ir.Op).kind = ir.OpKind.Container; + updatedElementXrefs.add(op.xref); + } + if (op.kind === ir.OpKind.ElementStart && op.tag === CONTAINER_TAG) { // Transmute the `ElementStart` instruction to `ContainerStart`. (op as ir.Op).kind = ir.OpKind.ContainerStart; diff --git a/packages/compiler/src/template/pipeline/src/phases/reify.ts b/packages/compiler/src/template/pipeline/src/phases/reify.ts index 83de37c823a..fb847151da3 100644 --- a/packages/compiler/src/template/pipeline/src/phases/reify.ts +++ b/packages/compiler/src/template/pipeline/src/phases/reify.ts @@ -87,7 +87,7 @@ function reifyCreateOperations(unit: CompilationUnit, ops: ir.OpList