Skip to content

Template pipeline leaves behind unnecessary restore/reset view calls in the presence of @let #66286

@crisbeto

Description

@crisbeto

Variables are generated in the pipeline by inserting references to all the symbols within the scope and then later cleaning up the unused ones in an optimization pass. When generating the scope for listener instructions, we expose all the @let declarations in the same view (see) which leads us to generate ɵɵrestoreView and ɵɵresetView calls, however if the @let reference isn't used within the listener, the variable optimization phase only removes the variable that reads it and not the ɵɵrestoreView/ɵɵresetView calls.

For example, if we take the following template:

@let unused = 1;
<button (click)="noop()"></button>

It produces the following code before optimization:

if (rf & 1) {
  const _r1 = ɵɵgetCurrentView();
  ɵɵdeclareLet(0);
  ɵɵdomElementStart(1, "button", 0);
  ɵɵdomListener(
    "click",
    function TestComp_Template_button_click_1_listener() {
      const ctx_r1 = ɵɵrestoreView(_r1);
      const unused_r3 = ɵɵreadContextLet(0);
      return ɵɵresetView(ctx.noop());
    }
  );
  ɵɵdomElementEnd();
}
if (rf & 2) {
  const unused_r4 = ɵɵstoreLet(1);
}

Which becomes the following after optimization:

if (rf & 1) {
  const _r1 = ɵɵgetCurrentView();
  ɵɵdomElementStart(0, "button", 0);
  ɵɵdomListener(
    "click",
    function TestComp_Template_button_click_0_listener() {
      ɵɵrestoreView(_r1);
      return ɵɵresetView(ctx.noop());
    }
  );
  ɵɵdomElementEnd();
}
if (rf & 2) {
  1;
}

The ɵɵrestoreView and ɵɵresetView calls aren't necessary and should be removed, because there aren't any reads of the unused @let.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions