GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Template Pipeline: Ingestion of bindings on `ng-template`s by dylhunn · Pull Request #53457 · angular/angular

Conversation

@dylhunn

@dylhunn dylhunn commented Dec 8, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Consider code like the following:

<ng-template literal1="litVal" [prop1]="propVal" [attr.attr1]="attrVal" [class.class1]="classVal">
  <h1 *ngIf="true" literal2="litVal" [prop2]="propVal" [attr.attr2]="attrVal" [class.class2]="classVal">
  </h1>
</ng-template>

It's quite difficult to follow how the template pipeline ingests these bindings today. attrs vs templateAttrs, text vs const bindings, structural vs raw templates, bindings on templates that don't target them, property bindings in the Template const field, etc. It's overwhelming.

Fear no longer! This PR is dedicated to fixing ingestion of bindings on templates. The end goal is to make binding ingestion philosophically consistent and understandable when reading. Also, I hope to put a stop to the presubmit failures related to template bindings.

Several commits fix individual, specific issues with bindings on templates. Along the way, I have performed major refactors of the binding ingestion code. This occasionally touches ops and phases, although the bulk of the work is in ingest.ts.

Read individual commit messages in order, for details.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

artaommahe and tonivj5 reacted with heart emoji
All reactions
  • ❤️ 2 reactions
@dylhunn dylhunn added target: patch This PR is targeted for the next patch release area: compiler Issues related to `ngc`, Angular's template compiler compiler: template pipeline labels Dec 8, 2023
@ngbot ngbot Bot added this to the Backlog milestone Dec 8, 2023
@dylhunn
dylhunn force-pushed the template-ingestion branch 17 times, most recently from 383f4c6 to 81c447f Compare December 9, 2023 23:27
@dylhunn
dylhunn marked this pull request as ready for review December 9, 2023 23:28
@dylhunn
dylhunn requested review from alxhub and mmalerba December 9, 2023 23:28
@dylhunn dylhunn added the action: review The PR is still awaiting reviews from at least one requested reviewer label Dec 9, 2023
dylhunn added 4 commits December 9, 2023 15:35
@dylhunn
refactor(compiler): Don't emit class and style bindings on structural…
d9b90a4
… template views

The Template Pipeline has had a number of tricky bugs involving bindings on structural elements.

Consider this template:

```
<div *ngIf="true" [class.bar]="field"></div>
```

We were incorrectly emitting `ɵɵclassProp` on *both* the template's view, and the inner view. The solution is to just emit an extracted attribute on the enclosing template, so it still shows up in the const array, but does not affect the update block.

We will refactor binding ingestion soon, but this commit improves our correctness before any big refactor.
@dylhunn
refactor(compiler): Simplify some code in ingest
bc85f44
Currently Template Pipeline's ingest phase is very complex, especially when it comes to ingesting bindings.

In this commit, we make some superficial simplifications, in preparation for a larger refactoring. For example, we pull out common code such as `convertAstWithInterpolation` and the `i18n.Message` checks. This enormously shrinks the main binding ingestion functions.

In addition, we reorder the binding kind and flags code above `ingestBindings`, so that `ingestBindings` and `ingestBinding` can be viewed together.
@dylhunn
refactor(compiler): Split up binding ingestion for elements and templ…
5472f83
…ates

Previously, we had `ingestBindings` and `ingestBinding`, which required tons of cases to support both elements and templates.

Now, we have two separate functions, `ingestElementBindings` and `ingestTemplateBindings`.

Thanks to the previous refactoring work, `ingestBinding` is now extremely compact. In fact, it's so compact that, in the elements case, it can just be inlined! Therefore, element binding ingestion is now quite easy to read.

The template case continues to be pretty gnarly, although I have already removed some code. In subsequent commits, we will simplify it even further.
@dylhunn
refactor(compiler): Eliminate BindingFlags and reorder parameters o…
64ff212
…f `createTemplateBinding`

It turns out that `BindingFlags.BindingTargetsTemplate` is actally a redundant property! It will be true in either of the following cases:
1. The template is a normal non-structural `ng-template`. We already know this from `TemplateKind`.
2. The binding came from `templateAttrs` (instead of `attrs`). We have this information in `BindingFlags.IsStructuralTemplateAttribute`.

Therefore, I can just eliminate `BindingFlags.BindingTargetsTemplate`. There's no reason to keep `BindingFlags` around for a single value, so I convert `BindingFlags.IsStructuralTemplateAttribute` to a boolean parameter (with the eventual goal of eliminating it entirely).

Additionally, because element binding ingestion now calls `ir.createBindingOp` inline, it was difficult to compare it to template binding ingestion, which uses the  `createTemplateBinding` helper. I have changed the parameter order of `createTemplateBinding` to closely mimic `ir.createBindingOp`. This will both make the code easier to read, and allow me to easily replace one with the other in the future.

Lastly: the template binding ingestion function is the site of much of the binding ingestion complexity. Add an explanatory function comment.
@dylhunn
dylhunn force-pushed the template-ingestion branch from 81c447f to cafbf59 Compare December 9, 2023 23:35
alxhub pushed a commit that referenced this pull request Dec 11, 2023
@dylhunn @alxhub
refactor(compiler): Fix animation bindings on structural elements (#5…
41955b8
…3457)

Consider the case:

```
<button *ngIf="true" [@anim]="field"></button>
```

Only the inner `button` should recieve a `property` instruction for the animation binding. We were previously emitting one for the implicit `ng-template` as well, and collecting it into the consts for the `ng-template`. Both of these issues are now fixed.

PR Close #53457
alxhub pushed a commit that referenced this pull request Dec 11, 2023
@dylhunn @alxhub
refactor(compiler): Make some fixups to template binidng ingestion (#…
9219642
…53457)

Responding to comments on #53457 about the previous sequence of template binding PRs.

PR Close #53457
alxhub pushed a commit that referenced this pull request Dec 11, 2023
@dylhunn @alxhub
refactor(compiler): Don't emit class and style bindings on structural…
1faa61f
… template views (#53457)

The Template Pipeline has had a number of tricky bugs involving bindings on structural elements.

Consider this template:

```
<div *ngIf="true" [class.bar]="field"></div>
```

We were incorrectly emitting `ɵɵclassProp` on *both* the template's view, and the inner view. The solution is to just emit an extracted attribute on the enclosing template, so it still shows up in the const array, but does not affect the update block.

We will refactor binding ingestion soon, but this commit improves our correctness before any big refactor.

PR Close #53457
alxhub pushed a commit that referenced this pull request Dec 11, 2023
@dylhunn @alxhub
refactor(compiler): Simplify some code in ingest (#53457)
876f90a
Currently Template Pipeline's ingest phase is very complex, especially when it comes to ingesting bindings.

In this commit, we make some superficial simplifications, in preparation for a larger refactoring. For example, we pull out common code such as `convertAstWithInterpolation` and the `i18n.Message` checks. This enormously shrinks the main binding ingestion functions.

In addition, we reorder the binding kind and flags code above `ingestBindings`, so that `ingestBindings` and `ingestBinding` can be viewed together.

PR Close #53457
alxhub pushed a commit that referenced this pull request Dec 11, 2023
@dylhunn @alxhub
refactor(compiler): Split up binding ingestion for elements and templ…
694e6ae
…ates (#53457)

Previously, we had `ingestBindings` and `ingestBinding`, which required tons of cases to support both elements and templates.

Now, we have two separate functions, `ingestElementBindings` and `ingestTemplateBindings`.

Thanks to the previous refactoring work, `ingestBinding` is now extremely compact. In fact, it's so compact that, in the elements case, it can just be inlined! Therefore, element binding ingestion is now quite easy to read.

The template case continues to be pretty gnarly, although I have already removed some code. In subsequent commits, we will simplify it even further.

PR Close #53457
alxhub pushed a commit that referenced this pull request Dec 11, 2023
@dylhunn @alxhub
refactor(compiler): Eliminate BindingFlags and reorder parameters o…
b2e5a20
…f `createTemplateBinding` (#53457)

It turns out that `BindingFlags.BindingTargetsTemplate` is actally a redundant property! It will be true in either of the following cases:
1. The template is a normal non-structural `ng-template`. We already know this from `TemplateKind`.
2. The binding came from `templateAttrs` (instead of `attrs`). We have this information in `BindingFlags.IsStructuralTemplateAttribute`.

Therefore, I can just eliminate `BindingFlags.BindingTargetsTemplate`. There's no reason to keep `BindingFlags` around for a single value, so I convert `BindingFlags.IsStructuralTemplateAttribute` to a boolean parameter (with the eventual goal of eliminating it entirely).

Additionally, because element binding ingestion now calls `ir.createBindingOp` inline, it was difficult to compare it to template binding ingestion, which uses the  `createTemplateBinding` helper. I have changed the parameter order of `createTemplateBinding` to closely mimic `ir.createBindingOp`. This will both make the code easier to read, and allow me to easily replace one with the other in the future.

Lastly: the template binding ingestion function is the site of much of the binding ingestion complexity. Add an explanatory function comment.

PR Close #53457
alxhub pushed a commit that referenced this pull request Dec 11, 2023
@dylhunn @alxhub
refactor(compiler): Fix some behavior with bindings on explicit `ng-t…
a15a012
…emplate` elements (#53457)

The behavior of explicit bindings on `ng-template`s was untested, and we differed from `TemplateDefinitionBuilder` significantly. We now have much more similar behavior, although not 100% identical.

For example, consider this templarte:
```
<ng-template l="l1" [p]="p1" [attr.a]="a1" [class.c]="c1"></ng-template>
```

It's not clear what a class binding on an `ng-template` would actually do. Nonetheless, it's well-defined behavior in TemplateDefinitionBuilder, which emits `property` instructions for all three bindings, and people actually do this in google3.

Note that some of these bindings don't really make much sense, but we have to support them for compatibility purposes.

See comments for an in-depth explanation of all the logic.

Also, add a test to exercise the problematic case.

PR Close #53457
alxhub pushed a commit that referenced this pull request Dec 11, 2023
@dylhunn @alxhub
refactor(compiler): Fix animation bindings on structural elements (#5…
7967d28
…3457)

Consider the case:

```
<button *ngIf="true" [@anim]="field"></button>
```

Only the inner `button` should recieve a `property` instruction for the animation binding. We were previously emitting one for the implicit `ng-template` as well, and collecting it into the consts for the `ng-template`. Both of these issues are now fixed.

PR Close #53457
alxhub pushed a commit that referenced this pull request Dec 11, 2023
@dylhunn @alxhub
refactor(compiler): Make some fixups to template binidng ingestion (#…
7fa791e
…53457)

Responding to comments on #53457 about the previous sequence of template binding PRs.

PR Close #53457
@angular-automatic-lock-bot

angular-automatic-lock-bot Bot commented Jan 11, 2024

Copy link
Copy Markdown

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@angular-automatic-lock-bot angular-automatic-lock-bot Bot locked and limited conversation to collaborators Jan 11, 2024
ChellappanRajan pushed a commit to ChellappanRajan/angular that referenced this pull request Jan 23, 2024
@dylhunn @ChellappanRajan
refactor(compiler): Don't emit class and style bindings on structural…
4dd5378
… template views (angular#53457)

The Template Pipeline has had a number of tricky bugs involving bindings on structural elements.

Consider this template:

```
<div *ngIf="true" [class.bar]="field"></div>
```

We were incorrectly emitting `ɵɵclassProp` on *both* the template's view, and the inner view. The solution is to just emit an extracted attribute on the enclosing template, so it still shows up in the const array, but does not affect the update block.

We will refactor binding ingestion soon, but this commit improves our correctness before any big refactor.

PR Close angular#53457
ChellappanRajan pushed a commit to ChellappanRajan/angular that referenced this pull request Jan 23, 2024
@dylhunn @ChellappanRajan
refactor(compiler): Simplify some code in ingest (angular#53457)
bf5a7a4
Currently Template Pipeline's ingest phase is very complex, especially when it comes to ingesting bindings.

In this commit, we make some superficial simplifications, in preparation for a larger refactoring. For example, we pull out common code such as `convertAstWithInterpolation` and the `i18n.Message` checks. This enormously shrinks the main binding ingestion functions.

In addition, we reorder the binding kind and flags code above `ingestBindings`, so that `ingestBindings` and `ingestBinding` can be viewed together.

PR Close angular#53457
ChellappanRajan pushed a commit to ChellappanRajan/angular that referenced this pull request Jan 23, 2024
@dylhunn @ChellappanRajan
refactor(compiler): Split up binding ingestion for elements and templ…
3d0a19e
…ates (angular#53457)

Previously, we had `ingestBindings` and `ingestBinding`, which required tons of cases to support both elements and templates.

Now, we have two separate functions, `ingestElementBindings` and `ingestTemplateBindings`.

Thanks to the previous refactoring work, `ingestBinding` is now extremely compact. In fact, it's so compact that, in the elements case, it can just be inlined! Therefore, element binding ingestion is now quite easy to read.

The template case continues to be pretty gnarly, although I have already removed some code. In subsequent commits, we will simplify it even further.

PR Close angular#53457
ChellappanRajan pushed a commit to ChellappanRajan/angular that referenced this pull request Jan 23, 2024
@dylhunn @ChellappanRajan
refactor(compiler): Eliminate BindingFlags and reorder parameters o…
87560ed
…f `createTemplateBinding` (angular#53457)

It turns out that `BindingFlags.BindingTargetsTemplate` is actally a redundant property! It will be true in either of the following cases:
1. The template is a normal non-structural `ng-template`. We already know this from `TemplateKind`.
2. The binding came from `templateAttrs` (instead of `attrs`). We have this information in `BindingFlags.IsStructuralTemplateAttribute`.

Therefore, I can just eliminate `BindingFlags.BindingTargetsTemplate`. There's no reason to keep `BindingFlags` around for a single value, so I convert `BindingFlags.IsStructuralTemplateAttribute` to a boolean parameter (with the eventual goal of eliminating it entirely).

Additionally, because element binding ingestion now calls `ir.createBindingOp` inline, it was difficult to compare it to template binding ingestion, which uses the  `createTemplateBinding` helper. I have changed the parameter order of `createTemplateBinding` to closely mimic `ir.createBindingOp`. This will both make the code easier to read, and allow me to easily replace one with the other in the future.

Lastly: the template binding ingestion function is the site of much of the binding ingestion complexity. Add an explanatory function comment.

PR Close angular#53457
ChellappanRajan pushed a commit to ChellappanRajan/angular that referenced this pull request Jan 23, 2024
@dylhunn @ChellappanRajan
refactor(compiler): Fix some behavior with bindings on explicit `ng-t…
8ae4547
…emplate` elements (angular#53457)

The behavior of explicit bindings on `ng-template`s was untested, and we differed from `TemplateDefinitionBuilder` significantly. We now have much more similar behavior, although not 100% identical.

For example, consider this templarte:
```
<ng-template l="l1" [p]="p1" [attr.a]="a1" [class.c]="c1"></ng-template>
```

It's not clear what a class binding on an `ng-template` would actually do. Nonetheless, it's well-defined behavior in TemplateDefinitionBuilder, which emits `property` instructions for all three bindings, and people actually do this in google3.

Note that some of these bindings don't really make much sense, but we have to support them for compatibility purposes.

See comments for an in-depth explanation of all the logic.

Also, add a test to exercise the problematic case.

PR Close angular#53457
ChellappanRajan pushed a commit to ChellappanRajan/angular that referenced this pull request Jan 23, 2024
@dylhunn @ChellappanRajan
refactor(compiler): Fix animation bindings on structural elements (an…
917e4a5
…gular#53457)

Consider the case:

```
<button *ngIf="true" [@anim]="field"></button>
```

Only the inner `button` should recieve a `property` instruction for the animation binding. We were previously emitting one for the implicit `ng-template` as well, and collecting it into the consts for the `ng-template`. Both of these issues are now fixed.

PR Close angular#53457
ChellappanRajan pushed a commit to ChellappanRajan/angular that referenced this pull request Jan 23, 2024
@dylhunn @ChellappanRajan
refactor(compiler): Make some fixups to template binidng ingestion (a…
144eea5
…ngular#53457)

Responding to comments on angular#53457 about the previous sequence of template binding PRs.

PR Close angular#53457
rlmestre pushed a commit to rlmestre/angular that referenced this pull request Jan 26, 2024
@dylhunn @rlmestre
refactor(compiler): Don't emit class and style bindings on structural…
6047da9
… template views (angular#53457)

The Template Pipeline has had a number of tricky bugs involving bindings on structural elements.

Consider this template:

```
<div *ngIf="true" [class.bar]="field"></div>
```

We were incorrectly emitting `ɵɵclassProp` on *both* the template's view, and the inner view. The solution is to just emit an extracted attribute on the enclosing template, so it still shows up in the const array, but does not affect the update block.

We will refactor binding ingestion soon, but this commit improves our correctness before any big refactor.

PR Close angular#53457
rlmestre pushed a commit to rlmestre/angular that referenced this pull request Jan 26, 2024
@dylhunn @rlmestre
refactor(compiler): Simplify some code in ingest (angular#53457)
acf3305
Currently Template Pipeline's ingest phase is very complex, especially when it comes to ingesting bindings.

In this commit, we make some superficial simplifications, in preparation for a larger refactoring. For example, we pull out common code such as `convertAstWithInterpolation` and the `i18n.Message` checks. This enormously shrinks the main binding ingestion functions.

In addition, we reorder the binding kind and flags code above `ingestBindings`, so that `ingestBindings` and `ingestBinding` can be viewed together.

PR Close angular#53457
rlmestre pushed a commit to rlmestre/angular that referenced this pull request Jan 26, 2024
@dylhunn @rlmestre
refactor(compiler): Split up binding ingestion for elements and templ…
54fd450
…ates (angular#53457)

Previously, we had `ingestBindings` and `ingestBinding`, which required tons of cases to support both elements and templates.

Now, we have two separate functions, `ingestElementBindings` and `ingestTemplateBindings`.

Thanks to the previous refactoring work, `ingestBinding` is now extremely compact. In fact, it's so compact that, in the elements case, it can just be inlined! Therefore, element binding ingestion is now quite easy to read.

The template case continues to be pretty gnarly, although I have already removed some code. In subsequent commits, we will simplify it even further.

PR Close angular#53457
rlmestre pushed a commit to rlmestre/angular that referenced this pull request Jan 26, 2024
@dylhunn @rlmestre
refactor(compiler): Eliminate BindingFlags and reorder parameters o…
1ac60f7
…f `createTemplateBinding` (angular#53457)

It turns out that `BindingFlags.BindingTargetsTemplate` is actally a redundant property! It will be true in either of the following cases:
1. The template is a normal non-structural `ng-template`. We already know this from `TemplateKind`.
2. The binding came from `templateAttrs` (instead of `attrs`). We have this information in `BindingFlags.IsStructuralTemplateAttribute`.

Therefore, I can just eliminate `BindingFlags.BindingTargetsTemplate`. There's no reason to keep `BindingFlags` around for a single value, so I convert `BindingFlags.IsStructuralTemplateAttribute` to a boolean parameter (with the eventual goal of eliminating it entirely).

Additionally, because element binding ingestion now calls `ir.createBindingOp` inline, it was difficult to compare it to template binding ingestion, which uses the  `createTemplateBinding` helper. I have changed the parameter order of `createTemplateBinding` to closely mimic `ir.createBindingOp`. This will both make the code easier to read, and allow me to easily replace one with the other in the future.

Lastly: the template binding ingestion function is the site of much of the binding ingestion complexity. Add an explanatory function comment.

PR Close angular#53457
rlmestre pushed a commit to rlmestre/angular that referenced this pull request Jan 26, 2024
@dylhunn @rlmestre
refactor(compiler): Fix some behavior with bindings on explicit `ng-t…
137c573
…emplate` elements (angular#53457)

The behavior of explicit bindings on `ng-template`s was untested, and we differed from `TemplateDefinitionBuilder` significantly. We now have much more similar behavior, although not 100% identical.

For example, consider this templarte:
```
<ng-template l="l1" [p]="p1" [attr.a]="a1" [class.c]="c1"></ng-template>
```

It's not clear what a class binding on an `ng-template` would actually do. Nonetheless, it's well-defined behavior in TemplateDefinitionBuilder, which emits `property` instructions for all three bindings, and people actually do this in google3.

Note that some of these bindings don't really make much sense, but we have to support them for compatibility purposes.

See comments for an in-depth explanation of all the logic.

Also, add a test to exercise the problematic case.

PR Close angular#53457
rlmestre pushed a commit to rlmestre/angular that referenced this pull request Jan 26, 2024
@dylhunn @rlmestre
refactor(compiler): Fix animation bindings on structural elements (an…
eb13865
…gular#53457)

Consider the case:

```
<button *ngIf="true" [@anim]="field"></button>
```

Only the inner `button` should recieve a `property` instruction for the animation binding. We were previously emitting one for the implicit `ng-template` as well, and collecting it into the consts for the `ng-template`. Both of these issues are now fixed.

PR Close angular#53457
rlmestre pushed a commit to rlmestre/angular that referenced this pull request Jan 26, 2024
@dylhunn @rlmestre
refactor(compiler): Make some fixups to template binidng ingestion (a…
42e7ca7
…ngular#53457)

Responding to comments on angular#53457 about the previous sequence of template binding PRs.

PR Close angular#53457
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Reviewers

1 more reviewer
@mmalerba mmalerba mmalerba approved these changes
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

action: merge The PR is ready for merge by the caretaker area: compiler Issues related to `ngc`, Angular's template compiler compiler: template pipeline merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note target: patch This PR is targeted for the next patch release

Projects

None yet

Milestone

Backlog

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@dylhunn @alxhub @mmalerba
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.