From deae02ecefe13ff6e6e8a13f987f744642ba3193 Mon Sep 17 00:00:00 2001 From: Alex Rickabaugh Date: Thu, 22 Dec 2022 11:55:18 -0500 Subject: [PATCH] refactor(compiler): pipeline phase to merge sequential elementstart/elementend (#48580) As an optimization, the runtime provides an `element()` instruction to use in place of `elementStart()` and `elementEnd()` when there are no instructions between them. This commit merges `ElementStart` and `ElementEnd` IR operations into `Element` operations in that special case. PR Close #48580 --- .../pipeline/src/phases/empty_elements.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 packages/compiler/src/template/pipeline/src/phases/empty_elements.ts diff --git a/packages/compiler/src/template/pipeline/src/phases/empty_elements.ts b/packages/compiler/src/template/pipeline/src/phases/empty_elements.ts new file mode 100644 index 00000000000..0cc8089a106 --- /dev/null +++ b/packages/compiler/src/template/pipeline/src/phases/empty_elements.ts @@ -0,0 +1,30 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as ir from '../../ir'; +import {ComponentCompilation} from '../compilation'; + +/** + * Replace sequences of `ElementStart` followed by `ElementEnd` with a condensed `Element` + * instruction. + */ +export function phaseEmptyElements(cpl: ComponentCompilation): void { + for (const [_, view] of cpl.views) { + for (const op of view.create) { + if (op.kind === ir.OpKind.ElementEnd && op.prev !== null && + op.prev.kind === ir.OpKind.ElementStart) { + // Transmute the `ElementStart` instruction to `Element`. This is safe as they're designed + // to be identical apart from the `kind`. + (op.prev as unknown as ir.ElementOp).kind = ir.OpKind.Element; + + // Remove the `ElementEnd` instruction. + ir.OpList.remove(op); + } + } + } +}